├── MicroClimate.cpp ├── README.md ├── TinyEngine ├── TinyEngine.h └── include │ ├── audio.cpp │ ├── event.cpp │ ├── helpers │ ├── color.h │ ├── helper.h │ ├── image.h │ └── object.h │ ├── imgui │ ├── LICENSE.txt │ ├── imconfig.h │ ├── imgui.cpp │ ├── imgui.h │ ├── imgui_demo.cpp │ ├── imgui_draw.cpp │ ├── imgui_impl_opengl3.cpp │ ├── imgui_impl_opengl3.h │ ├── imgui_impl_sdl.cpp │ ├── imgui_impl_sdl.h │ ├── imgui_internal.h │ ├── imgui_widgets.cpp │ ├── imstb_rectpack.h │ ├── imstb_textedit.h │ ├── imstb_truetype.h │ └── misc │ │ ├── README.txt │ │ ├── cpp │ │ ├── README.txt │ │ ├── imgui_stdlib.cpp │ │ └── imgui_stdlib.h │ │ ├── fonts │ │ ├── Cousine-Regular.ttf │ │ ├── DroidSans.ttf │ │ ├── Karla-Regular.ttf │ │ ├── ProggyClean.ttf │ │ ├── ProggyTiny.ttf │ │ ├── README.txt │ │ ├── Roboto-Medium.ttf │ │ └── binary_to_compressed_c.cpp │ │ ├── freetype │ │ ├── README.md │ │ ├── imgui_freetype.cpp │ │ └── imgui_freetype.h │ │ └── natvis │ │ ├── README.txt │ │ └── imgui.natvis │ ├── utility │ ├── instance.cpp │ ├── model.cpp │ ├── shader.cpp │ ├── target.cpp │ └── texture.cpp │ └── view.cpp ├── TinyFluid ├── TinyFluid.h └── include │ ├── helpers │ └── timer.h │ ├── render │ ├── color.h │ ├── input.cpp │ ├── input.h │ ├── view.cpp │ └── view.h │ └── src │ ├── algebra.h │ ├── shape.h │ ├── solve.h │ ├── space.h │ └── time.h ├── include ├── model.h ├── source.h └── terrain.h ├── makefile └── shader ├── default.fs ├── default.gs ├── default.vs ├── depth.fs └── depth.vs /MicroClimate.cpp: -------------------------------------------------------------------------------- 1 | #include "TinyEngine/TinyEngine.h" 2 | 3 | #define SIZE 100 4 | #include "TinyFluid/TinyFluid.h" 5 | 6 | #include "include/source.h" 7 | #include "include/terrain.h" 8 | #include "include/model.h" 9 | 10 | int main( int argc, char* args[] ) { 11 | 12 | //Initialize a Window 13 | Tiny::view.vsync = false; 14 | Tiny::window("TinyFluid Climate Test", 1200, 800); 15 | 16 | int n = 8; 17 | omp_set_num_threads(n); 18 | Eigen::setNbThreads(n); 19 | 20 | bool paused = true; 21 | 22 | //Add the Event Handler 23 | Tiny::event.handler = [&](){ 24 | if(!Tiny::event.press.empty() && Tiny::event.press.back() == SDLK_p) 25 | paused = !paused; 26 | if(Tiny::event.scroll.negy){ 27 | zoom *= 0.99; 28 | projection = glm::ortho(-(float)Tiny::view.WIDTH*zoom, (float)Tiny::view.WIDTH*zoom, -(float)Tiny::view.HEIGHT*zoom, (float)Tiny::view.HEIGHT*zoom, -800.0f, 500.0f); 29 | } 30 | if(Tiny::event.scroll.posy){ 31 | zoom /= 0.99; 32 | projection = glm::ortho(-(float)Tiny::view.WIDTH*zoom, (float)Tiny::view.WIDTH*zoom, -(float)Tiny::view.HEIGHT*zoom, (float)Tiny::view.HEIGHT*zoom, -800.0f, 500.0f); 33 | } 34 | if(Tiny::event.scroll.negx) 35 | camera = glm::rotate(camera, glm::radians(0.6f), glm::vec3(0.0f, 1.0f, 0.0f)); 36 | if(Tiny::event.scroll.posx) 37 | camera = glm::rotate(camera, glm::radians(-0.5f), glm::vec3(0.0f, 1.0f, 0.0f)); 38 | 39 | }; 40 | 41 | Field field; 42 | field.SEED = 100; 43 | field.initialize(); 44 | 45 | /* 46 | We want to pass the data to the shaders! 47 | 48 | Then we will give the model an additional property which we will later use. 49 | */ 50 | 51 | //Setup Shaders 52 | Shader shader({"shader/default.vs", "shader/default.gs", "shader/default.fs"}, {"in_Position", "in_Normal", "in_Color", "in_Cloud"}); 53 | Shader depth({"shader/depth.vs", "shader/depth.fs"}, {"in_Position"}); 54 | 55 | //Setup Rendering Billboards 56 | Billboard shadow(2000, 2000, false, true); 57 | Billboard image(1200, 800); 58 | Square2D flat; 59 | 60 | Model model(constructor, field.height.data()); 61 | model.shift(glm::vec3(-SIZE/2, -150, -SIZE/2)); //Translate Mesh 62 | 63 | //Cloud Vector! 64 | Eigen::ArrayXf cloud; 65 | 66 | //std::cout<<"Threads Allocated: "< true_cloud; 109 | 110 | //Execute the render loop 111 | int t = 0; 112 | 113 | Tiny::loop([&](){ 114 | 115 | camera = glm::rotate(camera, glm::radians(0.1f), glm::vec3(0.0f, 1.0f, 0.0f)); 116 | 117 | //Compute Relevant Rendering Quantities 118 | //clouds2 = source::CLOUD(field.humidity, field.P, field.temperature, 150.0); 119 | 120 | 121 | if(!paused){ 122 | 123 | camera = glm::rotate(camera, glm::radians(0.2f), glm::vec3(0.0f, 1.0f, 0.0f)); 124 | 125 | timer::benchmark([&](){ 126 | 127 | field.timestep(); 128 | 129 | }); 130 | 131 | cloud = (source::CLOUD(field.humidity, field.P, field.temperature, 100.0)).cast(); 132 | true_cloud.clear(); 133 | 134 | for(int i = 0; i < dim.x-1; i++){ 135 | for(int j = 0; j < dim.y-1; j++){ 136 | for(int k = 0; k < 6; k++){ 137 | true_cloud.push_back(cloud(i*dim.y+j)); //Jesus Christus 138 | } 139 | } 140 | } 141 | 142 | //This is a thing... 143 | 144 | glBindVertexArray(model.vao); 145 | glBindBuffer(GL_ARRAY_BUFFER, model.vbo[3]); 146 | glBufferData(GL_ARRAY_BUFFER, true_cloud.size()*sizeof(GLfloat), &true_cloud[0], GL_STATIC_DRAW); 147 | //glBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, cloud.size()*sizeof(float), cloud.data()); 148 | glEnableVertexAttribArray(3); 149 | glVertexAttribPointer(3, 1, GL_FLOAT, GL_FALSE, 0, 0); 150 | 151 | } 152 | 153 | }); 154 | 155 | Tiny::quit(); 156 | 157 | return 0; 158 | } 159 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MicroClimate 2 | Tiny Climate Simulation 3 | 4 | Transport Equation Solver: TinyFluid 5 | 6 | Rendered With: TinyEngine 7 | 8 | Finite Volume Navier Stokes solves for wind-patterns around terrain with pressure linked in. The terrain acts as a "choking" boundary condition - imagine a glass-pane sitting on top of the highest point of the terrain, parallel to sealevel. 9 | 10 | Transport equations move humidity and temperature around. 11 | 12 | Thermodynamics of water vapor, along with energy and mass transfer source terms, then give the climate dynamics. 13 | 14 | Detailed explanation to follow. 15 | -------------------------------------------------------------------------------- /TinyEngine/TinyEngine.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using Handle = std::function; 4 | using slist = std::initializer_list; 5 | 6 | #include "include/imgui/imgui.h" //Interface Dependencies 7 | #include "include/imgui/imgui_impl_sdl.h" 8 | #include "include/imgui/imgui_impl_opengl3.h" 9 | 10 | #include //Rendering Dependencies 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include "glm/gtc/matrix_transform.hpp" 17 | 18 | #include //File / Console IO 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | #include "include/utility/texture.cpp" //Utility Classes 25 | #include "include/utility/shader.cpp" 26 | #include "include/utility/model.cpp" 27 | #include "include/utility/instance.cpp" 28 | #include "include/utility/target.cpp" 29 | 30 | #include "include/view.cpp" 31 | #include "include/event.cpp" 32 | #include "include/audio.cpp" 33 | 34 | #include 35 | 36 | /* TINY ENGINE */ 37 | 38 | namespace Tiny { 39 | 40 | static View view; //Window and Interface (Requires Initialization) 41 | static Event event; //Event Handler 42 | static Audio audio; //Audio Processor (Requires Initialization) 43 | 44 | bool window(std::string windowName, int width, int height){ //Open a window 45 | if( SDL_Init( SDL_INIT_VIDEO ) < 0 ){ 46 | printf( "SDL could not initialize! Error: %s\n", SDL_GetError() ); 47 | return false; 48 | } 49 | 50 | SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); 51 | SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); 52 | SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2); 53 | SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8); 54 | 55 | if( !( IMG_Init( IMG_INIT_PNG ) & IMG_INIT_PNG ) ){ 56 | printf( "SDL_Image could not initialize! Error: %s\n", IMG_GetError() ); 57 | return false; 58 | } 59 | 60 | if( TTF_Init() == -1 ){ //for some reason this is -1 61 | printf( "SDL_ttf could not initialize! Error: %s\n", TTF_GetError() ); 62 | return false; 63 | } 64 | 65 | if(!view.init(windowName, width, height)){ //Start the View Class 66 | std::cout<<"Failed to launch visual interface."< 86 | void loop(F function, Args&&... args){ 87 | while(!event.quit){ 88 | 89 | if(Tiny::view.enabled){ 90 | event.input(); //Get Input 91 | event.handle(view); //Call the event-handling system 92 | } 93 | 94 | if(Tiny::audio.enabled) audio.process(); //Audio Processor 95 | 96 | function(args...); //User-defined Game Loop 97 | 98 | if(Tiny::view.enabled) view.render(); //Render View 99 | 100 | } 101 | } 102 | 103 | } 104 | -------------------------------------------------------------------------------- /TinyEngine/include/audio.cpp: -------------------------------------------------------------------------------- 1 | class Audio{ 2 | public: 3 | bool enabled = false; 4 | 5 | std::unordered_map sounds; 6 | std::deque unprocessed; 7 | 8 | bool init(); 9 | bool quit(); 10 | 11 | void load(slist in); 12 | void play(std::string sound); 13 | void process(); 14 | }; 15 | 16 | bool Audio::init(){ 17 | enabled = ( Mix_OpenAudio( 22050, MIX_DEFAULT_FORMAT, 2, 4096 ) != -1 ); 18 | return enabled; 19 | } 20 | 21 | void Audio::load(slist in){ 22 | for (auto& e: in){ 23 | Mix_Chunk* sound = Mix_LoadWAV( e.c_str() ); 24 | if(sound != NULL) 25 | sounds[e] = sound; 26 | else std::cout<<"Failed to load audio file "< active; 23 | std::deque press; 24 | 25 | //Movement Events 26 | bool mousemove = false; 27 | SDL_MouseMotionEvent mouse; 28 | 29 | //Clicking Events 30 | std::unordered_map click; //Active Buttons 31 | std::deque clicked; //Button Events 32 | 33 | Scroll scroll; 34 | SDL_Event windowEvent; //Window Resizing Event 35 | bool windowEventTrigger = false; 36 | }; 37 | 38 | void Event::input(){ 39 | if(SDL_PollEvent(&in) == 0) return; 40 | ImGui_ImplSDL2_ProcessEvent(&in); 41 | 42 | switch(in.type){ 43 | case SDL_QUIT: 44 | quit = true; 45 | break; 46 | case SDL_KEYDOWN: 47 | active[in.key.keysym.sym] = true; 48 | break; 49 | case SDL_KEYUP: 50 | active[in.key.keysym.sym] = false; 51 | press.push_front(in.key.keysym.sym); 52 | break; 53 | case SDL_MOUSEWHEEL: 54 | scroll.posy = (in.wheel.y > 0.99); 55 | scroll.negy = (in.wheel.y < -0.99); 56 | scroll.posx = (in.wheel.x > 0.99); 57 | scroll.negx = (in.wheel.x < -0.99); 58 | break; 59 | case SDL_MOUSEMOTION: 60 | mouse = in.motion; 61 | mousemove = true; 62 | break; 63 | case SDL_MOUSEBUTTONDOWN: 64 | click[in.button.button] = true; 65 | break; 66 | case SDL_MOUSEBUTTONUP: 67 | click[in.button.button] = false; 68 | clicked.push_front(in.button.button); 69 | break; 70 | case SDL_WINDOWEVENT: 71 | if(in.window.event == SDL_WINDOWEVENT_RESIZED){ 72 | windowEvent = in; 73 | windowEventTrigger = true; 74 | } 75 | break; 76 | default: 77 | break; 78 | } 79 | } 80 | 81 | void Event::handle(View &view){ 82 | 83 | if(windowEventTrigger){ 84 | view.WIDTH = windowEvent.window.data1; 85 | view.HEIGHT = windowEvent.window.data2; 86 | } 87 | 88 | (handler)(); //Call user-defined handler 89 | 90 | if(!press.empty()){ 91 | if(press.back() == SDLK_ESCAPE) //Toggle interface visibility 92 | view.showInterface = !view.showInterface; 93 | 94 | if(press.back() == SDLK_F11){ //Toggle fullscreen 95 | view.fullscreen = !view.fullscreen; 96 | if(!view.fullscreen) SDL_SetWindowFullscreen(view.gWindow, 0); 97 | else SDL_SetWindowFullscreen(view.gWindow, SDL_WINDOW_FULLSCREEN_DESKTOP); 98 | } 99 | 100 | press.pop_back(); 101 | } 102 | 103 | if(!clicked.empty()) clicked.pop_back(); //Reset Event Triggers 104 | scroll.reset(); 105 | mousemove = false; 106 | windowEventTrigger = false; 107 | } 108 | -------------------------------------------------------------------------------- /TinyEngine/include/helpers/color.h: -------------------------------------------------------------------------------- 1 | namespace color{ 2 | glm::vec3 black = glm::vec3(0.0); 3 | glm::vec3 white = glm::vec3(1.0); 4 | 5 | template 6 | T bezier(float t, std::vector points){ 7 | while(points.size() > 1){ //Recursive Linear Interpolations 8 | std::vector next; 9 | for(unsigned int i = 0; i < points.size()-1; i++) 10 | next.push_back( (1.0-t)*points[i] + t*points[i+1] ); 11 | points = next; 12 | } 13 | return points[0]; 14 | } 15 | 16 | template 17 | T bezier(float t, std::initializer_list p){ 18 | std::vector points; 19 | points.insert(points.end(), p.begin(), p.end()); 20 | return bezier(t, points); 21 | } 22 | 23 | glm::vec3 pick(int i, const int N){ 24 | int Z = (float)((i%N)); 25 | int Y = (float)((i/N)%N); 26 | int X = (float)((i/(N*N))%N); 27 | return glm::vec3(X, Y, Z)/glm::vec3(N-1.0f); 28 | } 29 | 30 | template 31 | int index(T c, const int N){ 32 | glm::vec3 w = glm::vec3(N-1.0f)*glm::vec3(N*N, N, 1); 33 | return c.x*w.x + c.y*w.y + c.z*w.z; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /TinyEngine/include/helpers/helper.h: -------------------------------------------------------------------------------- 1 | template 2 | T min(T a, T b){ 3 | return (a < b)?a:b; 4 | } 5 | 6 | template 7 | T max(T a, T b){ 8 | return (a > b)?a:b; 9 | } 10 | 11 | template 12 | T clamp(T t, T a, T b){ 13 | return (a > b)?a:b; 14 | } 15 | 16 | std::hash position_hash; 17 | float hashrand(int i){ 18 | return (float)(position_hash(std::to_string(i))%1000)/1000.0f; 19 | } 20 | -------------------------------------------------------------------------------- /TinyEngine/include/helpers/image.h: -------------------------------------------------------------------------------- 1 | namespace image { 2 | 3 | SDL_Surface* load(std::string path){ 4 | SDL_Surface* loaded = IMG_Load(path.c_str()); 5 | if(loaded == NULL) 6 | printf( "Unable to load image %s! SDL_image Error: %s\n", path.c_str(), IMG_GetError() ); 7 | SDL_Surface* optimized = SDL_ConvertSurfaceFormat(loaded, SDL_PIXELFORMAT_RGBA32, 0); 8 | SDL_FreeSurface(loaded); 9 | return optimized; 10 | } 11 | 12 | void save(SDL_Surface* surface, std::string path){ 13 | IMG_SavePNG(surface, path.c_str()); 14 | } 15 | 16 | template 17 | SDL_Surface* make(glm::vec2 size, T* data, std::function handle){ 18 | SDL_Surface *s = SDL_CreateRGBSurface(0, size.x, size.y, 32, 0, 0, 0, 0); 19 | SDL_LockSurface(s); 20 | 21 | unsigned char* img_raw = (unsigned char*)s->pixels; //Raw Data 22 | 23 | for(int i = 0; i < size.x*size.y; i++){ 24 | glm::vec4 color = handle(data[i]); //Construct from Algorithm 25 | *(img_raw+4*i) = (unsigned char)(255*color.x); 26 | *(img_raw+4*i+1) = (unsigned char)(255*color.y); 27 | *(img_raw+4*i+2) = (unsigned char)(255*color.z); 28 | *(img_raw+4*i+3) = (unsigned char)(255*color.w); 29 | } 30 | 31 | SDL_UnlockSurface(s); 32 | return s; 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /TinyEngine/include/helpers/object.h: -------------------------------------------------------------------------------- 1 | /* 2 | Model Loading Namespace from Object Files 3 | */ 4 | 5 | namespace obj{ 6 | 7 | //Get Colors from material list 8 | std::unordered_map materials(std::string file){ 9 | std::unordered_map mat; 10 | 11 | //Open the File 12 | std::ifstream in(file+".mtl", std::ios::in); 13 | if(in){ 14 | 15 | std::string line; 16 | std::string matname; 17 | while (getline(in, line)){ 18 | if(line[0] == '#') continue; //Ignore Comments 19 | 20 | if(line.substr(0, 6) == "newmtl") 21 | matname = line.substr(7); 22 | 23 | else if(line.substr(0, 2) == "Kd"){ 24 | float R, G, B; 25 | int m = std::sscanf(line.substr(3).c_str(), "%f %f %f\n", &R, &G, &B); 26 | if(m != 3) std::cout<<"Material Color Data was not read correctly."< load = [](Model* h, std::string file){ 38 | h->indexed = false; 39 | std::unordered_map mat = materials(file); 40 | 41 | //Temporary Buffers 42 | std::vector vertices; 43 | std::vector normals; 44 | 45 | std::ifstream in(file+".obj", std::ios::in); 46 | 47 | if(!in){ 48 | std::cout<<"Failed to open file "<> v.x; s >> v.y; s >> v.z; 68 | vertices.push_back(v); 69 | } 70 | 71 | else if(line.substr(0,3) == "vt"){ 72 | vt = true; 73 | /* 74 | std::istringstream s(line.substr(3)); 75 | glm::vec3 v; 76 | s >> v.x; s >> v.y; s >> v.z; 77 | ex_tex.push_back(v); //??? 78 | */ 79 | } 80 | 81 | //Extract Normal Information 82 | else if(line.substr(0,3) == "vn "){ 83 | std::istringstream s(line.substr(3)); 84 | glm::vec3 n; 85 | s >> n.x; s >> n.y; s >> n.z; 86 | normals.push_back(n); 87 | } 88 | 89 | else if(line.substr(0, 6) == "usemtl") 90 | color = mat[line.substr(7)]; 91 | 92 | //Map Index Information 93 | else if(line.substr(0,2) == "f "){ 94 | unsigned int vI[3], uI[3], nI[3]; 95 | if(normals.empty() && !vt){ //Simple Format 96 | int m = std::sscanf(line.substr(2).c_str(), "%d %d %d\n", &vI[0], &vI[1], &vI[2]); 97 | if(m != 3){ 98 | std::cout<<"Face data could not be read correctly."<indices.push_back(h->positions.size()/3); 112 | 113 | for(int i = 0; i < 3; i++){ 114 | h->positions.push_back(vertices[vI[i]-1].x); 115 | h->positions.push_back(vertices[vI[i]-1].y); 116 | h->positions.push_back(vertices[vI[i]-1].z); 117 | } 118 | if(!normals.empty()) 119 | for(int i = 0; i < 3; i++){ 120 | h->normals.push_back(normals[nI[i]-1].x); 121 | h->normals.push_back(normals[nI[i]-1].y); 122 | h->normals.push_back(normals[nI[i]-1].z); 123 | } 124 | else{ 125 | glm::vec3 a = vertices[vI[0]-1]; 126 | glm::vec3 b = vertices[vI[1]-1]; 127 | glm::vec3 c = vertices[vI[2]-1]; 128 | glm::vec3 n = glm::normalize(glm::cross(b-a, c-a)); 129 | for(int i = 0; i < 3; i++){ 130 | h->normals.push_back(n.x); 131 | h->normals.push_back(n.y); 132 | h->normals.push_back(n.z); 133 | } 134 | } 135 | for(int i = 0; i < 3; i++){ 136 | h->colors.push_back(color.x); 137 | h->colors.push_back(color.y); 138 | h->colors.push_back(color.z); 139 | h->colors.push_back(1.0); 140 | } 141 | } 142 | } 143 | 144 | in.close(); 145 | }; 146 | 147 | } 148 | -------------------------------------------------------------------------------- /TinyEngine/include/imgui/LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014-2019 Omar Cornut 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /TinyEngine/include/imgui/imconfig.h: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // COMPILE-TIME OPTIONS FOR DEAR IMGUI 3 | // Runtime options (clipboard callbacks, enabling various features, etc.) can generally be set via the ImGuiIO structure. 4 | // You can use ImGui::SetAllocatorFunctions() before calling ImGui::CreateContext() to rewire memory allocation functions. 5 | //----------------------------------------------------------------------------- 6 | // A) You may edit imconfig.h (and not overwrite it when updating Dear ImGui, or maintain a patch/branch with your modifications to imconfig.h) 7 | // B) or add configuration directives in your own file and compile with #define IMGUI_USER_CONFIG "myfilename.h" 8 | // If you do so you need to make sure that configuration settings are defined consistently _everywhere_ Dear ImGui is used, which include 9 | // the imgui*.cpp files but also _any_ of your code that uses Dear ImGui. This is because some compile-time options have an affect on data structures. 10 | // Defining those options in imconfig.h will ensure every compilation unit gets to see the same data structure layouts. 11 | // Call IMGUI_CHECKVERSION() from your .cpp files to verify that the data structures your files are using are matching the ones imgui.cpp is using. 12 | //----------------------------------------------------------------------------- 13 | 14 | #pragma once 15 | 16 | //---- Define assertion handler. Defaults to calling assert(). 17 | //#define IM_ASSERT(_EXPR) MyAssert(_EXPR) 18 | //#define IM_ASSERT(_EXPR) ((void)(_EXPR)) // Disable asserts 19 | 20 | //---- Define attributes of all API symbols declarations, e.g. for DLL under Windows 21 | // Using dear imgui via a shared library is not recommended, because of function call overhead and because we don't guarantee backward nor forward ABI compatibility. 22 | //#define IMGUI_API __declspec( dllexport ) 23 | //#define IMGUI_API __declspec( dllimport ) 24 | 25 | //---- Don't define obsolete functions/enums names. Consider enabling from time to time after updating to avoid using soon-to-be obsolete function/names. 26 | //#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS 27 | 28 | //---- Don't implement demo windows functionality (ShowDemoWindow()/ShowStyleEditor()/ShowUserGuide() methods will be empty) 29 | // It is very strongly recommended to NOT disable the demo windows during development. Please read the comments in imgui_demo.cpp. 30 | //#define IMGUI_DISABLE_DEMO_WINDOWS 31 | //#define IMGUI_DISABLE_METRICS_WINDOW 32 | 33 | //---- Don't implement some functions to reduce linkage requirements. 34 | //#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS // [Win32] Don't implement default clipboard handler. Won't use and link with OpenClipboard/GetClipboardData/CloseClipboard etc. 35 | //#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] Don't implement default IME handler. Won't use and link with ImmGetContext/ImmSetCompositionWindow. 36 | //#define IMGUI_DISABLE_WIN32_FUNCTIONS // [Win32] Won't use and link with any Win32 function (clipboard, ime). 37 | //#define IMGUI_ENABLE_OSX_DEFAULT_CLIPBOARD_FUNCTIONS // [OSX] Implement default OSX clipboard handler (need to link with '-framework ApplicationServices'). 38 | //#define IMGUI_DISABLE_FORMAT_STRING_FUNCTIONS // Don't implement ImFormatString/ImFormatStringV so you can implement them yourself if you don't want to link with vsnprintf. 39 | //#define IMGUI_DISABLE_MATH_FUNCTIONS // Don't implement ImFabs/ImSqrt/ImPow/ImFmod/ImCos/ImSin/ImAcos/ImAtan2 wrapper so you can implement them yourself. Declare your prototypes in imconfig.h. 40 | //#define IMGUI_DISABLE_DEFAULT_ALLOCATORS // Don't implement default allocators calling malloc()/free() to avoid linking with them. You will need to call ImGui::SetAllocatorFunctions(). 41 | 42 | //---- Include imgui_user.h at the end of imgui.h as a convenience 43 | //#define IMGUI_INCLUDE_IMGUI_USER_H 44 | 45 | //---- Pack colors to BGRA8 instead of RGBA8 (to avoid converting from one to another) 46 | //#define IMGUI_USE_BGRA_PACKED_COLOR 47 | 48 | //---- Avoid multiple STB libraries implementations, or redefine path/filenames to prioritize another version 49 | // By default the embedded implementations are declared static and not available outside of imgui cpp files. 50 | //#define IMGUI_STB_TRUETYPE_FILENAME "my_folder/stb_truetype.h" 51 | //#define IMGUI_STB_RECT_PACK_FILENAME "my_folder/stb_rect_pack.h" 52 | //#define IMGUI_DISABLE_STB_TRUETYPE_IMPLEMENTATION 53 | //#define IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION 54 | 55 | //---- Define constructor and implicit cast operators to convert back<>forth between your math types and ImVec2/ImVec4. 56 | // This will be inlined as part of ImVec2 and ImVec4 class declarations. 57 | /* 58 | #define IM_VEC2_CLASS_EXTRA \ 59 | ImVec2(const MyVec2& f) { x = f.x; y = f.y; } \ 60 | operator MyVec2() const { return MyVec2(x,y); } 61 | 62 | #define IM_VEC4_CLASS_EXTRA \ 63 | ImVec4(const MyVec4& f) { x = f.x; y = f.y; z = f.z; w = f.w; } \ 64 | operator MyVec4() const { return MyVec4(x,y,z,w); } 65 | */ 66 | 67 | //---- Using 32-bits vertex indices (default is 16-bits) is one way to allow large meshes with more than 64K vertices. 68 | // Your renderer back-end will need to support it (most example renderer back-ends support both 16/32-bits indices). 69 | // Another way to allow large meshes while keeping 16-bits indices is to handle ImDrawCmd::VtxOffset in your renderer. 70 | // Read about ImGuiBackendFlags_RendererHasVtxOffset for details. 71 | //#define ImDrawIdx unsigned int 72 | 73 | //---- Override ImDrawCallback signature (will need to modify renderer back-ends accordingly) 74 | //struct ImDrawList; 75 | //struct ImDrawCmd; 76 | //typedef void (*MyImDrawCallback)(const ImDrawList* draw_list, const ImDrawCmd* cmd, void* my_renderer_user_data); 77 | //#define ImDrawCallback MyImDrawCallback 78 | 79 | //---- Debug Tools 80 | // Use 'Metrics->Tools->Item Picker' to pick widgets with the mouse and break into them for easy debugging. 81 | //#define IM_DEBUG_BREAK IM_ASSERT(0) 82 | //#define IM_DEBUG_BREAK __debugbreak() 83 | // Have the Item Picker break in the ItemAdd() function instead of ItemHoverable() - which is earlier in the code, will catch a few extra items, allow picking items other than Hovered one. 84 | // This adds a small runtime cost which is why it is not enabled by default. 85 | //#define IMGUI_DEBUG_TOOL_ITEM_PICKER_EX 86 | 87 | //---- Tip: You can add extra functions within the ImGui:: namespace, here or in your own headers files. 88 | 89 | /* 90 | namespace ImGui 91 | { 92 | } 93 | */ 94 | -------------------------------------------------------------------------------- /TinyEngine/include/imgui/imgui_impl_opengl3.cpp: -------------------------------------------------------------------------------- 1 | // dear imgui: Renderer for modern OpenGL with shaders / programmatic pipeline 2 | // - Desktop GL: 3.x 4.x 3 | // - Embedded GL: ES 2.0 (WebGL 1.0), ES 3.0 (WebGL 2.0) 4 | // This needs to be used along with a Platform Binding (e.g. GLFW, SDL, Win32, custom..) 5 | 6 | // Implemented features: 7 | // [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. 8 | // [x] Renderer: Desktop GL only: Support for large meshes (64k+ vertices) with 16-bits indices. 9 | 10 | // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. 11 | // If you are new to dear imgui, read examples/README.txt and read the documentation at the top of imgui.cpp. 12 | // https://github.com/ocornut/imgui 13 | 14 | // CHANGELOG 15 | // (minor and older changes stripped away, please see git history for details) 16 | // 2019-05-29: OpenGL: Desktop GL only: Added support for large mesh (64K+ vertices), enable ImGuiBackendFlags_RendererHasVtxOffset flag. 17 | // 2019-04-30: OpenGL: Added support for special ImDrawCallback_ResetRenderState callback to reset render state. 18 | // 2019-03-29: OpenGL: Not calling glBindBuffer more than necessary in the render loop. 19 | // 2019-03-15: OpenGL: Added a dummy GL call + comments in ImGui_ImplOpenGL3_Init() to detect uninitialized GL function loaders early. 20 | // 2019-03-03: OpenGL: Fix support for ES 2.0 (WebGL 1.0). 21 | // 2019-02-20: OpenGL: Fix for OSX not supporting OpenGL 4.5, we don't try to read GL_CLIP_ORIGIN even if defined by the headers/loader. 22 | // 2019-02-11: OpenGL: Projecting clipping rectangles correctly using draw_data->FramebufferScale to allow multi-viewports for retina display. 23 | // 2019-02-01: OpenGL: Using GLSL 410 shaders for any version over 410 (e.g. 430, 450). 24 | // 2018-11-30: Misc: Setting up io.BackendRendererName so it can be displayed in the About Window. 25 | // 2018-11-13: OpenGL: Support for GL 4.5's glClipControl(GL_UPPER_LEFT) / GL_CLIP_ORIGIN. 26 | // 2018-08-29: OpenGL: Added support for more OpenGL loaders: glew and glad, with comments indicative that any loader can be used. 27 | // 2018-08-09: OpenGL: Default to OpenGL ES 3 on iOS and Android. GLSL version default to "#version 300 ES". 28 | // 2018-07-30: OpenGL: Support for GLSL 300 ES and 410 core. Fixes for Emscripten compilation. 29 | // 2018-07-10: OpenGL: Support for more GLSL versions (based on the GLSL version string). Added error output when shaders fail to compile/link. 30 | // 2018-06-08: Misc: Extracted imgui_impl_opengl3.cpp/.h away from the old combined GLFW/SDL+OpenGL3 examples. 31 | // 2018-06-08: OpenGL: Use draw_data->DisplayPos and draw_data->DisplaySize to setup projection matrix and clipping rectangle. 32 | // 2018-05-25: OpenGL: Removed unnecessary backup/restore of GL_ELEMENT_ARRAY_BUFFER_BINDING since this is part of the VAO state. 33 | // 2018-05-14: OpenGL: Making the call to glBindSampler() optional so 3.2 context won't fail if the function is a NULL pointer. 34 | // 2018-03-06: OpenGL: Added const char* glsl_version parameter to ImGui_ImplOpenGL3_Init() so user can override the GLSL version e.g. "#version 150". 35 | // 2018-02-23: OpenGL: Create the VAO in the render function so the setup can more easily be used with multiple shared GL context. 36 | // 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplSdlGL3_RenderDrawData() in the .h file so you can call it yourself. 37 | // 2018-01-07: OpenGL: Changed GLSL shader version from 330 to 150. 38 | // 2017-09-01: OpenGL: Save and restore current bound sampler. Save and restore current polygon mode. 39 | // 2017-05-01: OpenGL: Fixed save and restore of current blend func state. 40 | // 2017-05-01: OpenGL: Fixed save and restore of current GL_ACTIVE_TEXTURE. 41 | // 2016-09-05: OpenGL: Fixed save and restore of current scissor rectangle. 42 | // 2016-07-29: OpenGL: Explicitly setting GL_UNPACK_ROW_LENGTH to reduce issues because SDL changes it. (#752) 43 | 44 | //---------------------------------------- 45 | // OpenGL GLSL GLSL 46 | // version version string 47 | //---------------------------------------- 48 | // 2.0 110 "#version 110" 49 | // 2.1 120 "#version 120" 50 | // 3.0 130 "#version 130" 51 | // 3.1 140 "#version 140" 52 | // 3.2 150 "#version 150" 53 | // 3.3 330 "#version 330 core" 54 | // 4.0 400 "#version 400 core" 55 | // 4.1 410 "#version 410 core" 56 | // 4.2 420 "#version 410 core" 57 | // 4.3 430 "#version 430 core" 58 | // ES 2.0 100 "#version 100" = WebGL 1.0 59 | // ES 3.0 300 "#version 300 es" = WebGL 2.0 60 | //---------------------------------------- 61 | 62 | #if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS) 63 | #define _CRT_SECURE_NO_WARNINGS 64 | #endif 65 | 66 | #include "imgui.h" 67 | #include "imgui_impl_opengl3.h" 68 | #include 69 | #if defined(_MSC_VER) && _MSC_VER <= 1500 // MSVC 2008 or earlier 70 | #include // intptr_t 71 | #else 72 | #include // intptr_t 73 | #endif 74 | #if defined(__APPLE__) 75 | #include "TargetConditionals.h" 76 | #endif 77 | 78 | // Auto-detect GL version 79 | #if !defined(IMGUI_IMPL_OPENGL_ES2) && !defined(IMGUI_IMPL_OPENGL_ES3) 80 | #if (defined(__APPLE__) && (TARGET_OS_IOS || TARGET_OS_TV)) || (defined(__ANDROID__)) 81 | #define IMGUI_IMPL_OPENGL_ES3 // iOS, Android -> GL ES 3, "#version 300 es" 82 | #elif defined(__EMSCRIPTEN__) 83 | #define IMGUI_IMPL_OPENGL_ES2 // Emscripten -> GL ES 2, "#version 100" 84 | #endif 85 | #endif 86 | 87 | #if defined(IMGUI_IMPL_OPENGL_ES2) 88 | #include 89 | #elif defined(IMGUI_IMPL_OPENGL_ES3) 90 | #if (defined(__APPLE__) && (TARGET_OS_IOS || TARGET_OS_TV)) 91 | #include // Use GL ES 3 92 | #else 93 | #include // Use GL ES 3 94 | #endif 95 | #else 96 | // About Desktop OpenGL function loaders: 97 | // Modern desktop OpenGL doesn't have a standard portable header file to load OpenGL function pointers. 98 | // Helper libraries are often used for this purpose! Here we are supporting a few common ones (gl3w, glew, glad). 99 | // You may use another loader/header of your choice (glext, glLoadGen, etc.), or chose to manually implement your own. 100 | #if defined(IMGUI_IMPL_OPENGL_LOADER_GL3W) 101 | #include // Needs to be initialized with gl3wInit() in user's code 102 | #elif defined(IMGUI_IMPL_OPENGL_LOADER_GLEW) 103 | #include // Needs to be initialized with glewInit() in user's code 104 | #elif defined(IMGUI_IMPL_OPENGL_LOADER_GLAD) 105 | #include // Needs to be initialized with gladLoadGL() in user's code 106 | #else 107 | #include IMGUI_IMPL_OPENGL_LOADER_CUSTOM 108 | #endif 109 | #endif 110 | 111 | // Desktop GL has glDrawElementsBaseVertex() which GL ES and WebGL don't have. 112 | #if defined(IMGUI_IMPL_OPENGL_ES2) || defined(IMGUI_IMPL_OPENGL_ES3) 113 | #define IMGUI_IMPL_OPENGL_HAS_DRAW_WITH_BASE_VERTEX 0 114 | #else 115 | #define IMGUI_IMPL_OPENGL_HAS_DRAW_WITH_BASE_VERTEX 1 116 | #endif 117 | 118 | // OpenGL Data 119 | static char g_GlslVersionString[32] = ""; 120 | static GLuint g_FontTexture = 0; 121 | static GLuint g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; 122 | static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; // Uniforms location 123 | static int g_AttribLocationVtxPos = 0, g_AttribLocationVtxUV = 0, g_AttribLocationVtxColor = 0; // Vertex attributes location 124 | static unsigned int g_VboHandle = 0, g_ElementsHandle = 0; 125 | 126 | // Functions 127 | bool ImGui_ImplOpenGL3_Init(const char* glsl_version) 128 | { 129 | // Setup back-end capabilities flags 130 | ImGuiIO& io = ImGui::GetIO(); 131 | io.BackendRendererName = "imgui_impl_opengl3"; 132 | #if IMGUI_IMPL_OPENGL_HAS_DRAW_WITH_BASE_VERTEX 133 | io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes. 134 | #endif 135 | 136 | // Store GLSL version string so we can refer to it later in case we recreate shaders. Note: GLSL version is NOT the same as GL version. Leave this to NULL if unsure. 137 | #if defined(IMGUI_IMPL_OPENGL_ES2) 138 | if (glsl_version == NULL) 139 | glsl_version = "#version 100"; 140 | #elif defined(IMGUI_IMPL_OPENGL_ES3) 141 | if (glsl_version == NULL) 142 | glsl_version = "#version 300 es"; 143 | #else 144 | if (glsl_version == NULL) 145 | glsl_version = "#version 130"; 146 | #endif 147 | IM_ASSERT((int)strlen(glsl_version) + 2 < IM_ARRAYSIZE(g_GlslVersionString)); 148 | strcpy(g_GlslVersionString, glsl_version); 149 | strcat(g_GlslVersionString, "\n"); 150 | 151 | // Make a dummy GL call (we don't actually need the result) 152 | // IF YOU GET A CRASH HERE: it probably means that you haven't initialized the OpenGL function loader used by this code. 153 | // Desktop OpenGL 3/4 need a function loader. See the IMGUI_IMPL_OPENGL_LOADER_xxx explanation above. 154 | GLint current_texture; 155 | glGetIntegerv(GL_TEXTURE_BINDING_2D, ¤t_texture); 156 | 157 | return true; 158 | } 159 | 160 | void ImGui_ImplOpenGL3_Shutdown() 161 | { 162 | ImGui_ImplOpenGL3_DestroyDeviceObjects(); 163 | } 164 | 165 | void ImGui_ImplOpenGL3_NewFrame() 166 | { 167 | if (!g_FontTexture) 168 | ImGui_ImplOpenGL3_CreateDeviceObjects(); 169 | } 170 | 171 | static void ImGui_ImplOpenGL3_SetupRenderState(ImDrawData* draw_data, int fb_width, int fb_height, GLuint vertex_array_object) 172 | { 173 | // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, polygon fill 174 | glEnable(GL_BLEND); 175 | glBlendEquation(GL_FUNC_ADD); 176 | glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 177 | glDisable(GL_CULL_FACE); 178 | glDisable(GL_DEPTH_TEST); 179 | glEnable(GL_SCISSOR_TEST); 180 | #ifdef GL_POLYGON_MODE 181 | glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); 182 | #endif 183 | 184 | // Setup viewport, orthographic projection matrix 185 | // Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayPos is (0,0) for single viewport apps. 186 | glViewport(0, 0, (GLsizei)fb_width, (GLsizei)fb_height); 187 | float L = draw_data->DisplayPos.x; 188 | float R = draw_data->DisplayPos.x + draw_data->DisplaySize.x; 189 | float T = draw_data->DisplayPos.y; 190 | float B = draw_data->DisplayPos.y + draw_data->DisplaySize.y; 191 | const float ortho_projection[4][4] = 192 | { 193 | { 2.0f/(R-L), 0.0f, 0.0f, 0.0f }, 194 | { 0.0f, 2.0f/(T-B), 0.0f, 0.0f }, 195 | { 0.0f, 0.0f, -1.0f, 0.0f }, 196 | { (R+L)/(L-R), (T+B)/(B-T), 0.0f, 1.0f }, 197 | }; 198 | glUseProgram(g_ShaderHandle); 199 | glUniform1i(g_AttribLocationTex, 0); 200 | glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); 201 | #ifdef GL_SAMPLER_BINDING 202 | glBindSampler(0, 0); // We use combined texture/sampler state. Applications using GL 3.3 may set that otherwise. 203 | #endif 204 | 205 | (void)vertex_array_object; 206 | #ifndef IMGUI_IMPL_OPENGL_ES2 207 | glBindVertexArray(vertex_array_object); 208 | #endif 209 | 210 | // Bind vertex/index buffers and setup attributes for ImDrawVert 211 | glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); 212 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_ElementsHandle); 213 | glEnableVertexAttribArray(g_AttribLocationVtxPos); 214 | glEnableVertexAttribArray(g_AttribLocationVtxUV); 215 | glEnableVertexAttribArray(g_AttribLocationVtxColor); 216 | glVertexAttribPointer(g_AttribLocationVtxPos, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, pos)); 217 | glVertexAttribPointer(g_AttribLocationVtxUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, uv)); 218 | glVertexAttribPointer(g_AttribLocationVtxColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, col)); 219 | } 220 | 221 | // OpenGL3 Render function. 222 | // (this used to be set in io.RenderDrawListsFn and called by ImGui::Render(), but you can now call this directly from your main loop) 223 | // Note that this implementation is little overcomplicated because we are saving/setting up/restoring every OpenGL state explicitly, in order to be able to run within any OpenGL engine that doesn't do so. 224 | void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data) 225 | { 226 | // Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates) 227 | int fb_width = (int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x); 228 | int fb_height = (int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y); 229 | if (fb_width <= 0 || fb_height <= 0) 230 | return; 231 | 232 | // Backup GL state 233 | GLenum last_active_texture; glGetIntegerv(GL_ACTIVE_TEXTURE, (GLint*)&last_active_texture); 234 | glActiveTexture(GL_TEXTURE0); 235 | GLint last_program; glGetIntegerv(GL_CURRENT_PROGRAM, &last_program); 236 | GLint last_texture; glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); 237 | #ifdef GL_SAMPLER_BINDING 238 | GLint last_sampler; glGetIntegerv(GL_SAMPLER_BINDING, &last_sampler); 239 | #endif 240 | GLint last_array_buffer; glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &last_array_buffer); 241 | #ifndef IMGUI_IMPL_OPENGL_ES2 242 | GLint last_vertex_array_object; glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &last_vertex_array_object); 243 | #endif 244 | #ifdef GL_POLYGON_MODE 245 | GLint last_polygon_mode[2]; glGetIntegerv(GL_POLYGON_MODE, last_polygon_mode); 246 | #endif 247 | GLint last_viewport[4]; glGetIntegerv(GL_VIEWPORT, last_viewport); 248 | GLint last_scissor_box[4]; glGetIntegerv(GL_SCISSOR_BOX, last_scissor_box); 249 | GLenum last_blend_src_rgb; glGetIntegerv(GL_BLEND_SRC_RGB, (GLint*)&last_blend_src_rgb); 250 | GLenum last_blend_dst_rgb; glGetIntegerv(GL_BLEND_DST_RGB, (GLint*)&last_blend_dst_rgb); 251 | GLenum last_blend_src_alpha; glGetIntegerv(GL_BLEND_SRC_ALPHA, (GLint*)&last_blend_src_alpha); 252 | GLenum last_blend_dst_alpha; glGetIntegerv(GL_BLEND_DST_ALPHA, (GLint*)&last_blend_dst_alpha); 253 | GLenum last_blend_equation_rgb; glGetIntegerv(GL_BLEND_EQUATION_RGB, (GLint*)&last_blend_equation_rgb); 254 | GLenum last_blend_equation_alpha; glGetIntegerv(GL_BLEND_EQUATION_ALPHA, (GLint*)&last_blend_equation_alpha); 255 | GLboolean last_enable_blend = glIsEnabled(GL_BLEND); 256 | GLboolean last_enable_cull_face = glIsEnabled(GL_CULL_FACE); 257 | GLboolean last_enable_depth_test = glIsEnabled(GL_DEPTH_TEST); 258 | GLboolean last_enable_scissor_test = glIsEnabled(GL_SCISSOR_TEST); 259 | bool clip_origin_lower_left = true; 260 | #if defined(GL_CLIP_ORIGIN) && !defined(__APPLE__) 261 | GLenum last_clip_origin = 0; glGetIntegerv(GL_CLIP_ORIGIN, (GLint*)&last_clip_origin); // Support for GL 4.5's glClipControl(GL_UPPER_LEFT) 262 | if (last_clip_origin == GL_UPPER_LEFT) 263 | clip_origin_lower_left = false; 264 | #endif 265 | 266 | // Setup desired GL state 267 | // Recreate the VAO every time (this is to easily allow multiple GL contexts to be rendered to. VAO are not shared among GL contexts) 268 | // The renderer would actually work without any VAO bound, but then our VertexAttrib calls would overwrite the default one currently bound. 269 | GLuint vertex_array_object = 0; 270 | #ifndef IMGUI_IMPL_OPENGL_ES2 271 | glGenVertexArrays(1, &vertex_array_object); 272 | #endif 273 | ImGui_ImplOpenGL3_SetupRenderState(draw_data, fb_width, fb_height, vertex_array_object); 274 | 275 | // Will project scissor/clipping rectangles into framebuffer space 276 | ImVec2 clip_off = draw_data->DisplayPos; // (0,0) unless using multi-viewports 277 | ImVec2 clip_scale = draw_data->FramebufferScale; // (1,1) unless using retina display which are often (2,2) 278 | 279 | // Render command lists 280 | for (int n = 0; n < draw_data->CmdListsCount; n++) 281 | { 282 | const ImDrawList* cmd_list = draw_data->CmdLists[n]; 283 | 284 | // Upload vertex/index buffers 285 | glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)cmd_list->VtxBuffer.Size * sizeof(ImDrawVert), (const GLvoid*)cmd_list->VtxBuffer.Data, GL_STREAM_DRAW); 286 | glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx), (const GLvoid*)cmd_list->IdxBuffer.Data, GL_STREAM_DRAW); 287 | 288 | for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++) 289 | { 290 | const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i]; 291 | if (pcmd->UserCallback != NULL) 292 | { 293 | // User callback, registered via ImDrawList::AddCallback() 294 | // (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.) 295 | if (pcmd->UserCallback == ImDrawCallback_ResetRenderState) 296 | ImGui_ImplOpenGL3_SetupRenderState(draw_data, fb_width, fb_height, vertex_array_object); 297 | else 298 | pcmd->UserCallback(cmd_list, pcmd); 299 | } 300 | else 301 | { 302 | // Project scissor/clipping rectangles into framebuffer space 303 | ImVec4 clip_rect; 304 | clip_rect.x = (pcmd->ClipRect.x - clip_off.x) * clip_scale.x; 305 | clip_rect.y = (pcmd->ClipRect.y - clip_off.y) * clip_scale.y; 306 | clip_rect.z = (pcmd->ClipRect.z - clip_off.x) * clip_scale.x; 307 | clip_rect.w = (pcmd->ClipRect.w - clip_off.y) * clip_scale.y; 308 | 309 | if (clip_rect.x < fb_width && clip_rect.y < fb_height && clip_rect.z >= 0.0f && clip_rect.w >= 0.0f) 310 | { 311 | // Apply scissor/clipping rectangle 312 | if (clip_origin_lower_left) 313 | glScissor((int)clip_rect.x, (int)(fb_height - clip_rect.w), (int)(clip_rect.z - clip_rect.x), (int)(clip_rect.w - clip_rect.y)); 314 | else 315 | glScissor((int)clip_rect.x, (int)clip_rect.y, (int)clip_rect.z, (int)clip_rect.w); // Support for GL 4.5 rarely used glClipControl(GL_UPPER_LEFT) 316 | 317 | // Bind texture, Draw 318 | glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); 319 | #if IMGUI_IMPL_OPENGL_HAS_DRAW_WITH_BASE_VERTEX 320 | glDrawElementsBaseVertex(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, (void*)(intptr_t)(pcmd->IdxOffset * sizeof(ImDrawIdx)), (GLint)pcmd->VtxOffset); 321 | #else 322 | glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, (void*)(intptr_t)(pcmd->IdxOffset * sizeof(ImDrawIdx))); 323 | #endif 324 | } 325 | } 326 | } 327 | } 328 | 329 | // Destroy the temporary VAO 330 | #ifndef IMGUI_IMPL_OPENGL_ES2 331 | glDeleteVertexArrays(1, &vertex_array_object); 332 | #endif 333 | 334 | // Restore modified GL state 335 | glUseProgram(last_program); 336 | glBindTexture(GL_TEXTURE_2D, last_texture); 337 | #ifdef GL_SAMPLER_BINDING 338 | glBindSampler(0, last_sampler); 339 | #endif 340 | glActiveTexture(last_active_texture); 341 | #ifndef IMGUI_IMPL_OPENGL_ES2 342 | glBindVertexArray(last_vertex_array_object); 343 | #endif 344 | glBindBuffer(GL_ARRAY_BUFFER, last_array_buffer); 345 | glBlendEquationSeparate(last_blend_equation_rgb, last_blend_equation_alpha); 346 | glBlendFuncSeparate(last_blend_src_rgb, last_blend_dst_rgb, last_blend_src_alpha, last_blend_dst_alpha); 347 | if (last_enable_blend) glEnable(GL_BLEND); else glDisable(GL_BLEND); 348 | if (last_enable_cull_face) glEnable(GL_CULL_FACE); else glDisable(GL_CULL_FACE); 349 | if (last_enable_depth_test) glEnable(GL_DEPTH_TEST); else glDisable(GL_DEPTH_TEST); 350 | if (last_enable_scissor_test) glEnable(GL_SCISSOR_TEST); else glDisable(GL_SCISSOR_TEST); 351 | #ifdef GL_POLYGON_MODE 352 | glPolygonMode(GL_FRONT_AND_BACK, (GLenum)last_polygon_mode[0]); 353 | #endif 354 | glViewport(last_viewport[0], last_viewport[1], (GLsizei)last_viewport[2], (GLsizei)last_viewport[3]); 355 | glScissor(last_scissor_box[0], last_scissor_box[1], (GLsizei)last_scissor_box[2], (GLsizei)last_scissor_box[3]); 356 | } 357 | 358 | bool ImGui_ImplOpenGL3_CreateFontsTexture() 359 | { 360 | // Build texture atlas 361 | ImGuiIO& io = ImGui::GetIO(); 362 | unsigned char* pixels; 363 | int width, height; 364 | io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits (75% of the memory is wasted, but default font is so small) because it is more likely to be compatible with user's existing shaders. If your ImTextureId represent a higher-level concept than just a GL texture id, consider calling GetTexDataAsAlpha8() instead to save on GPU memory. 365 | 366 | // Upload texture to graphics system 367 | GLint last_texture; 368 | glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); 369 | glGenTextures(1, &g_FontTexture); 370 | glBindTexture(GL_TEXTURE_2D, g_FontTexture); 371 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 372 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 373 | #ifdef GL_UNPACK_ROW_LENGTH 374 | glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); 375 | #endif 376 | glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); 377 | 378 | // Store our identifier 379 | io.Fonts->TexID = (ImTextureID)(intptr_t)g_FontTexture; 380 | 381 | // Restore state 382 | glBindTexture(GL_TEXTURE_2D, last_texture); 383 | 384 | return true; 385 | } 386 | 387 | void ImGui_ImplOpenGL3_DestroyFontsTexture() 388 | { 389 | if (g_FontTexture) 390 | { 391 | ImGuiIO& io = ImGui::GetIO(); 392 | glDeleteTextures(1, &g_FontTexture); 393 | io.Fonts->TexID = 0; 394 | g_FontTexture = 0; 395 | } 396 | } 397 | 398 | // If you get an error please report on github. You may try different GL context version or GLSL version. See GL<>GLSL version table at the top of this file. 399 | static bool CheckShader(GLuint handle, const char* desc) 400 | { 401 | GLint status = 0, log_length = 0; 402 | glGetShaderiv(handle, GL_COMPILE_STATUS, &status); 403 | glGetShaderiv(handle, GL_INFO_LOG_LENGTH, &log_length); 404 | if ((GLboolean)status == GL_FALSE) 405 | fprintf(stderr, "ERROR: ImGui_ImplOpenGL3_CreateDeviceObjects: failed to compile %s!\n", desc); 406 | if (log_length > 1) 407 | { 408 | ImVector buf; 409 | buf.resize((int)(log_length + 1)); 410 | glGetShaderInfoLog(handle, log_length, NULL, (GLchar*)buf.begin()); 411 | fprintf(stderr, "%s\n", buf.begin()); 412 | } 413 | return (GLboolean)status == GL_TRUE; 414 | } 415 | 416 | // If you get an error please report on GitHub. You may try different GL context version or GLSL version. 417 | static bool CheckProgram(GLuint handle, const char* desc) 418 | { 419 | GLint status = 0, log_length = 0; 420 | glGetProgramiv(handle, GL_LINK_STATUS, &status); 421 | glGetProgramiv(handle, GL_INFO_LOG_LENGTH, &log_length); 422 | if ((GLboolean)status == GL_FALSE) 423 | fprintf(stderr, "ERROR: ImGui_ImplOpenGL3_CreateDeviceObjects: failed to link %s! (with GLSL '%s')\n", desc, g_GlslVersionString); 424 | if (log_length > 1) 425 | { 426 | ImVector buf; 427 | buf.resize((int)(log_length + 1)); 428 | glGetProgramInfoLog(handle, log_length, NULL, (GLchar*)buf.begin()); 429 | fprintf(stderr, "%s\n", buf.begin()); 430 | } 431 | return (GLboolean)status == GL_TRUE; 432 | } 433 | 434 | bool ImGui_ImplOpenGL3_CreateDeviceObjects() 435 | { 436 | // Backup GL state 437 | GLint last_texture, last_array_buffer; 438 | glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); 439 | glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &last_array_buffer); 440 | #ifndef IMGUI_IMPL_OPENGL_ES2 441 | GLint last_vertex_array; 442 | glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &last_vertex_array); 443 | #endif 444 | 445 | // Parse GLSL version string 446 | int glsl_version = 130; 447 | sscanf(g_GlslVersionString, "#version %d", &glsl_version); 448 | 449 | const GLchar* vertex_shader_glsl_120 = 450 | "uniform mat4 ProjMtx;\n" 451 | "attribute vec2 Position;\n" 452 | "attribute vec2 UV;\n" 453 | "attribute vec4 Color;\n" 454 | "varying vec2 Frag_UV;\n" 455 | "varying vec4 Frag_Color;\n" 456 | "void main()\n" 457 | "{\n" 458 | " Frag_UV = UV;\n" 459 | " Frag_Color = Color;\n" 460 | " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" 461 | "}\n"; 462 | 463 | const GLchar* vertex_shader_glsl_130 = 464 | "uniform mat4 ProjMtx;\n" 465 | "in vec2 Position;\n" 466 | "in vec2 UV;\n" 467 | "in vec4 Color;\n" 468 | "out vec2 Frag_UV;\n" 469 | "out vec4 Frag_Color;\n" 470 | "void main()\n" 471 | "{\n" 472 | " Frag_UV = UV;\n" 473 | " Frag_Color = Color;\n" 474 | " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" 475 | "}\n"; 476 | 477 | const GLchar* vertex_shader_glsl_300_es = 478 | "precision mediump float;\n" 479 | "layout (location = 0) in vec2 Position;\n" 480 | "layout (location = 1) in vec2 UV;\n" 481 | "layout (location = 2) in vec4 Color;\n" 482 | "uniform mat4 ProjMtx;\n" 483 | "out vec2 Frag_UV;\n" 484 | "out vec4 Frag_Color;\n" 485 | "void main()\n" 486 | "{\n" 487 | " Frag_UV = UV;\n" 488 | " Frag_Color = Color;\n" 489 | " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" 490 | "}\n"; 491 | 492 | const GLchar* vertex_shader_glsl_410_core = 493 | "layout (location = 0) in vec2 Position;\n" 494 | "layout (location = 1) in vec2 UV;\n" 495 | "layout (location = 2) in vec4 Color;\n" 496 | "uniform mat4 ProjMtx;\n" 497 | "out vec2 Frag_UV;\n" 498 | "out vec4 Frag_Color;\n" 499 | "void main()\n" 500 | "{\n" 501 | " Frag_UV = UV;\n" 502 | " Frag_Color = Color;\n" 503 | " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" 504 | "}\n"; 505 | 506 | const GLchar* fragment_shader_glsl_120 = 507 | "#ifdef GL_ES\n" 508 | " precision mediump float;\n" 509 | "#endif\n" 510 | "uniform sampler2D Texture;\n" 511 | "varying vec2 Frag_UV;\n" 512 | "varying vec4 Frag_Color;\n" 513 | "void main()\n" 514 | "{\n" 515 | " gl_FragColor = Frag_Color * texture2D(Texture, Frag_UV.st);\n" 516 | "}\n"; 517 | 518 | const GLchar* fragment_shader_glsl_130 = 519 | "uniform sampler2D Texture;\n" 520 | "in vec2 Frag_UV;\n" 521 | "in vec4 Frag_Color;\n" 522 | "out vec4 Out_Color;\n" 523 | "void main()\n" 524 | "{\n" 525 | " Out_Color = Frag_Color * texture(Texture, Frag_UV.st);\n" 526 | "}\n"; 527 | 528 | const GLchar* fragment_shader_glsl_300_es = 529 | "precision mediump float;\n" 530 | "uniform sampler2D Texture;\n" 531 | "in vec2 Frag_UV;\n" 532 | "in vec4 Frag_Color;\n" 533 | "layout (location = 0) out vec4 Out_Color;\n" 534 | "void main()\n" 535 | "{\n" 536 | " Out_Color = Frag_Color * texture(Texture, Frag_UV.st);\n" 537 | "}\n"; 538 | 539 | const GLchar* fragment_shader_glsl_410_core = 540 | "in vec2 Frag_UV;\n" 541 | "in vec4 Frag_Color;\n" 542 | "uniform sampler2D Texture;\n" 543 | "layout (location = 0) out vec4 Out_Color;\n" 544 | "void main()\n" 545 | "{\n" 546 | " Out_Color = Frag_Color * texture(Texture, Frag_UV.st);\n" 547 | "}\n"; 548 | 549 | // Select shaders matching our GLSL versions 550 | const GLchar* vertex_shader = NULL; 551 | const GLchar* fragment_shader = NULL; 552 | if (glsl_version < 130) 553 | { 554 | vertex_shader = vertex_shader_glsl_120; 555 | fragment_shader = fragment_shader_glsl_120; 556 | } 557 | else if (glsl_version >= 410) 558 | { 559 | vertex_shader = vertex_shader_glsl_410_core; 560 | fragment_shader = fragment_shader_glsl_410_core; 561 | } 562 | else if (glsl_version == 300) 563 | { 564 | vertex_shader = vertex_shader_glsl_300_es; 565 | fragment_shader = fragment_shader_glsl_300_es; 566 | } 567 | else 568 | { 569 | vertex_shader = vertex_shader_glsl_130; 570 | fragment_shader = fragment_shader_glsl_130; 571 | } 572 | 573 | // Create shaders 574 | const GLchar* vertex_shader_with_version[2] = { g_GlslVersionString, vertex_shader }; 575 | g_VertHandle = glCreateShader(GL_VERTEX_SHADER); 576 | glShaderSource(g_VertHandle, 2, vertex_shader_with_version, NULL); 577 | glCompileShader(g_VertHandle); 578 | CheckShader(g_VertHandle, "vertex shader"); 579 | 580 | const GLchar* fragment_shader_with_version[2] = { g_GlslVersionString, fragment_shader }; 581 | g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER); 582 | glShaderSource(g_FragHandle, 2, fragment_shader_with_version, NULL); 583 | glCompileShader(g_FragHandle); 584 | CheckShader(g_FragHandle, "fragment shader"); 585 | 586 | g_ShaderHandle = glCreateProgram(); 587 | glAttachShader(g_ShaderHandle, g_VertHandle); 588 | glAttachShader(g_ShaderHandle, g_FragHandle); 589 | glLinkProgram(g_ShaderHandle); 590 | CheckProgram(g_ShaderHandle, "shader program"); 591 | 592 | g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture"); 593 | g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx"); 594 | g_AttribLocationVtxPos = glGetAttribLocation(g_ShaderHandle, "Position"); 595 | g_AttribLocationVtxUV = glGetAttribLocation(g_ShaderHandle, "UV"); 596 | g_AttribLocationVtxColor = glGetAttribLocation(g_ShaderHandle, "Color"); 597 | 598 | // Create buffers 599 | glGenBuffers(1, &g_VboHandle); 600 | glGenBuffers(1, &g_ElementsHandle); 601 | 602 | ImGui_ImplOpenGL3_CreateFontsTexture(); 603 | 604 | // Restore modified GL state 605 | glBindTexture(GL_TEXTURE_2D, last_texture); 606 | glBindBuffer(GL_ARRAY_BUFFER, last_array_buffer); 607 | #ifndef IMGUI_IMPL_OPENGL_ES2 608 | glBindVertexArray(last_vertex_array); 609 | #endif 610 | 611 | return true; 612 | } 613 | 614 | void ImGui_ImplOpenGL3_DestroyDeviceObjects() 615 | { 616 | if (g_VboHandle) glDeleteBuffers(1, &g_VboHandle); 617 | if (g_ElementsHandle) glDeleteBuffers(1, &g_ElementsHandle); 618 | g_VboHandle = g_ElementsHandle = 0; 619 | 620 | if (g_ShaderHandle && g_VertHandle) glDetachShader(g_ShaderHandle, g_VertHandle); 621 | if (g_VertHandle) glDeleteShader(g_VertHandle); 622 | g_VertHandle = 0; 623 | 624 | if (g_ShaderHandle && g_FragHandle) glDetachShader(g_ShaderHandle, g_FragHandle); 625 | if (g_FragHandle) glDeleteShader(g_FragHandle); 626 | g_FragHandle = 0; 627 | 628 | if (g_ShaderHandle) glDeleteProgram(g_ShaderHandle); 629 | g_ShaderHandle = 0; 630 | 631 | ImGui_ImplOpenGL3_DestroyFontsTexture(); 632 | } 633 | -------------------------------------------------------------------------------- /TinyEngine/include/imgui/imgui_impl_opengl3.h: -------------------------------------------------------------------------------- 1 | // dear imgui: Renderer for modern OpenGL with shaders / programmatic pipeline 2 | // - Desktop GL: 3.x 4.x 3 | // - Embedded GL: ES 2.0 (WebGL 1.0), ES 3.0 (WebGL 2.0) 4 | // This needs to be used along with a Platform Binding (e.g. GLFW, SDL, Win32, custom..) 5 | 6 | // Implemented features: 7 | // [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. 8 | // [x] Renderer: Desktop GL only: Support for large meshes (64k+ vertices) with 16-bits indices. 9 | 10 | // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. 11 | // If you are new to dear imgui, read examples/README.txt and read the documentation at the top of imgui.cpp. 12 | // https://github.com/ocornut/imgui 13 | 14 | // About Desktop OpenGL function loaders: 15 | // Modern desktop OpenGL doesn't have a standard portable header file to load OpenGL function pointers. 16 | // Helper libraries are often used for this purpose! Here we are supporting a few common ones (gl3w, glew, glad). 17 | // You may use another loader/header of your choice (glext, glLoadGen, etc.), or chose to manually implement your own. 18 | 19 | // About GLSL version: 20 | // The 'glsl_version' initialization parameter should be NULL (default) or a "#version XXX" string. 21 | // On computer platform the GLSL version default to "#version 130". On OpenGL ES 3 platform it defaults to "#version 300 es" 22 | // Only override if your GL version doesn't handle this GLSL version. See GLSL version table at the top of imgui_impl_opengl3.cpp. 23 | 24 | #pragma once 25 | 26 | // Specific OpenGL versions 27 | //#define IMGUI_IMPL_OPENGL_ES2 // Auto-detected on Emscripten 28 | //#define IMGUI_IMPL_OPENGL_ES3 // Auto-detected on iOS/Android 29 | 30 | // Set default OpenGL3 loader to be gl3w 31 | #if !defined(IMGUI_IMPL_OPENGL_LOADER_GL3W) \ 32 | && !defined(IMGUI_IMPL_OPENGL_LOADER_GLEW) \ 33 | && !defined(IMGUI_IMPL_OPENGL_LOADER_GLAD) \ 34 | && !defined(IMGUI_IMPL_OPENGL_LOADER_CUSTOM) 35 | #define IMGUI_IMPL_OPENGL_LOADER_GL3W 36 | #endif 37 | 38 | IMGUI_IMPL_API bool ImGui_ImplOpenGL3_Init(const char* glsl_version = NULL); 39 | IMGUI_IMPL_API void ImGui_ImplOpenGL3_Shutdown(); 40 | IMGUI_IMPL_API void ImGui_ImplOpenGL3_NewFrame(); 41 | IMGUI_IMPL_API void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data); 42 | 43 | // Called by Init/NewFrame/Shutdown 44 | IMGUI_IMPL_API bool ImGui_ImplOpenGL3_CreateFontsTexture(); 45 | IMGUI_IMPL_API void ImGui_ImplOpenGL3_DestroyFontsTexture(); 46 | IMGUI_IMPL_API bool ImGui_ImplOpenGL3_CreateDeviceObjects(); 47 | IMGUI_IMPL_API void ImGui_ImplOpenGL3_DestroyDeviceObjects(); 48 | -------------------------------------------------------------------------------- /TinyEngine/include/imgui/imgui_impl_sdl.cpp: -------------------------------------------------------------------------------- 1 | // dear imgui: Platform Binding for SDL2 2 | // This needs to be used along with a Renderer (e.g. DirectX11, OpenGL3, Vulkan..) 3 | // (Info: SDL2 is a cross-platform general purpose library for handling windows, inputs, graphics context creation, etc.) 4 | // (Requires: SDL 2.0. Prefer SDL 2.0.4+ for full feature support.) 5 | 6 | // Implemented features: 7 | // [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. 8 | // [X] Platform: Clipboard support. 9 | // [X] Platform: Keyboard arrays indexed using SDL_SCANCODE_* codes, e.g. ImGui::IsKeyPressed(SDL_SCANCODE_SPACE). 10 | // [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'. 11 | // Missing features: 12 | // [ ] Platform: SDL2 handling of IME under Windows appears to be broken and it explicitly disable the regular Windows IME. You can restore Windows IME by compiling SDL with SDL_DISABLE_WINDOWS_IME. 13 | 14 | // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. 15 | // If you are new to dear imgui, read examples/README.txt and read the documentation at the top of imgui.cpp. 16 | // https://github.com/ocornut/imgui 17 | 18 | // CHANGELOG 19 | // (minor and older changes stripped away, please see git history for details) 20 | // 2019-07-21: Inputs: Added mapping for ImGuiKey_KeyPadEnter. 21 | // 2019-04-23: Inputs: Added support for SDL_GameController (if ImGuiConfigFlags_NavEnableGamepad is set by user application). 22 | // 2019-03-12: Misc: Preserve DisplayFramebufferScale when main window is minimized. 23 | // 2018-12-21: Inputs: Workaround for Android/iOS which don't seem to handle focus related calls. 24 | // 2018-11-30: Misc: Setting up io.BackendPlatformName so it can be displayed in the About Window. 25 | // 2018-11-14: Changed the signature of ImGui_ImplSDL2_ProcessEvent() to take a 'const SDL_Event*'. 26 | // 2018-08-01: Inputs: Workaround for Emscripten which doesn't seem to handle focus related calls. 27 | // 2018-06-29: Inputs: Added support for the ImGuiMouseCursor_Hand cursor. 28 | // 2018-06-08: Misc: Extracted imgui_impl_sdl.cpp/.h away from the old combined SDL2+OpenGL/Vulkan examples. 29 | // 2018-06-08: Misc: ImGui_ImplSDL2_InitForOpenGL() now takes a SDL_GLContext parameter. 30 | // 2018-05-09: Misc: Fixed clipboard paste memory leak (we didn't call SDL_FreeMemory on the data returned by SDL_GetClipboardText). 31 | // 2018-03-20: Misc: Setup io.BackendFlags ImGuiBackendFlags_HasMouseCursors flag + honor ImGuiConfigFlags_NoMouseCursorChange flag. 32 | // 2018-02-16: Inputs: Added support for mouse cursors, honoring ImGui::GetMouseCursor() value. 33 | // 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves. 34 | // 2018-02-06: Inputs: Added mapping for ImGuiKey_Space. 35 | // 2018-02-05: Misc: Using SDL_GetPerformanceCounter() instead of SDL_GetTicks() to be able to handle very high framerate (1000+ FPS). 36 | // 2018-02-05: Inputs: Keyboard mapping is using scancodes everywhere instead of a confusing mixture of keycodes and scancodes. 37 | // 2018-01-20: Inputs: Added Horizontal Mouse Wheel support. 38 | // 2018-01-19: Inputs: When available (SDL 2.0.4+) using SDL_CaptureMouse() to retrieve coordinates outside of client area when dragging. Otherwise (SDL 2.0.3 and before) testing for SDL_WINDOW_INPUT_FOCUS instead of SDL_WINDOW_MOUSE_FOCUS. 39 | // 2018-01-18: Inputs: Added mapping for ImGuiKey_Insert. 40 | // 2017-08-25: Inputs: MousePos set to -FLT_MAX,-FLT_MAX when mouse is unavailable/missing (instead of -1,-1). 41 | // 2016-10-15: Misc: Added a void* user_data parameter to Clipboard function handlers. 42 | 43 | #include "imgui.h" 44 | #include "imgui_impl_sdl.h" 45 | 46 | // SDL 47 | #include 48 | #include 49 | #if defined(__APPLE__) 50 | #include "TargetConditionals.h" 51 | #endif 52 | 53 | #define SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE SDL_VERSION_ATLEAST(2,0,4) 54 | #define SDL_HAS_VULKAN SDL_VERSION_ATLEAST(2,0,6) 55 | 56 | // Data 57 | static SDL_Window* g_Window = NULL; 58 | static Uint64 g_Time = 0; 59 | static bool g_MousePressed[3] = { false, false, false }; 60 | static SDL_Cursor* g_MouseCursors[ImGuiMouseCursor_COUNT] = { 0 }; 61 | static char* g_ClipboardTextData = NULL; 62 | 63 | static const char* ImGui_ImplSDL2_GetClipboardText(void*) 64 | { 65 | if (g_ClipboardTextData) 66 | SDL_free(g_ClipboardTextData); 67 | g_ClipboardTextData = SDL_GetClipboardText(); 68 | return g_ClipboardTextData; 69 | } 70 | 71 | static void ImGui_ImplSDL2_SetClipboardText(void*, const char* text) 72 | { 73 | SDL_SetClipboardText(text); 74 | } 75 | 76 | // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. 77 | // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application. 78 | // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application. 79 | // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags. 80 | // If you have multiple SDL events and some of them are not meant to be used by dear imgui, you may need to filter events based on their windowID field. 81 | bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event) 82 | { 83 | ImGuiIO& io = ImGui::GetIO(); 84 | switch (event->type) 85 | { 86 | case SDL_MOUSEWHEEL: 87 | { 88 | if (event->wheel.x > 0) io.MouseWheelH += 1; 89 | if (event->wheel.x < 0) io.MouseWheelH -= 1; 90 | if (event->wheel.y > 0) io.MouseWheel += 1; 91 | if (event->wheel.y < 0) io.MouseWheel -= 1; 92 | return true; 93 | } 94 | case SDL_MOUSEBUTTONDOWN: 95 | { 96 | if (event->button.button == SDL_BUTTON_LEFT) g_MousePressed[0] = true; 97 | if (event->button.button == SDL_BUTTON_RIGHT) g_MousePressed[1] = true; 98 | if (event->button.button == SDL_BUTTON_MIDDLE) g_MousePressed[2] = true; 99 | return true; 100 | } 101 | case SDL_TEXTINPUT: 102 | { 103 | io.AddInputCharactersUTF8(event->text.text); 104 | return true; 105 | } 106 | case SDL_KEYDOWN: 107 | case SDL_KEYUP: 108 | { 109 | int key = event->key.keysym.scancode; 110 | IM_ASSERT(key >= 0 && key < IM_ARRAYSIZE(io.KeysDown)); 111 | io.KeysDown[key] = (event->type == SDL_KEYDOWN); 112 | io.KeyShift = ((SDL_GetModState() & KMOD_SHIFT) != 0); 113 | io.KeyCtrl = ((SDL_GetModState() & KMOD_CTRL) != 0); 114 | io.KeyAlt = ((SDL_GetModState() & KMOD_ALT) != 0); 115 | io.KeySuper = ((SDL_GetModState() & KMOD_GUI) != 0); 116 | return true; 117 | } 118 | } 119 | return false; 120 | } 121 | 122 | static bool ImGui_ImplSDL2_Init(SDL_Window* window) 123 | { 124 | g_Window = window; 125 | 126 | // Setup back-end capabilities flags 127 | ImGuiIO& io = ImGui::GetIO(); 128 | io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional) 129 | io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used) 130 | io.BackendPlatformName = "imgui_impl_sdl"; 131 | 132 | // Keyboard mapping. ImGui will use those indices to peek into the io.KeysDown[] array. 133 | io.KeyMap[ImGuiKey_Tab] = SDL_SCANCODE_TAB; 134 | io.KeyMap[ImGuiKey_LeftArrow] = SDL_SCANCODE_LEFT; 135 | io.KeyMap[ImGuiKey_RightArrow] = SDL_SCANCODE_RIGHT; 136 | io.KeyMap[ImGuiKey_UpArrow] = SDL_SCANCODE_UP; 137 | io.KeyMap[ImGuiKey_DownArrow] = SDL_SCANCODE_DOWN; 138 | io.KeyMap[ImGuiKey_PageUp] = SDL_SCANCODE_PAGEUP; 139 | io.KeyMap[ImGuiKey_PageDown] = SDL_SCANCODE_PAGEDOWN; 140 | io.KeyMap[ImGuiKey_Home] = SDL_SCANCODE_HOME; 141 | io.KeyMap[ImGuiKey_End] = SDL_SCANCODE_END; 142 | io.KeyMap[ImGuiKey_Insert] = SDL_SCANCODE_INSERT; 143 | io.KeyMap[ImGuiKey_Delete] = SDL_SCANCODE_DELETE; 144 | io.KeyMap[ImGuiKey_Backspace] = SDL_SCANCODE_BACKSPACE; 145 | io.KeyMap[ImGuiKey_Space] = SDL_SCANCODE_SPACE; 146 | io.KeyMap[ImGuiKey_Enter] = SDL_SCANCODE_RETURN; 147 | io.KeyMap[ImGuiKey_Escape] = SDL_SCANCODE_ESCAPE; 148 | io.KeyMap[ImGuiKey_KeyPadEnter] = SDL_SCANCODE_RETURN2; 149 | io.KeyMap[ImGuiKey_A] = SDL_SCANCODE_A; 150 | io.KeyMap[ImGuiKey_C] = SDL_SCANCODE_C; 151 | io.KeyMap[ImGuiKey_V] = SDL_SCANCODE_V; 152 | io.KeyMap[ImGuiKey_X] = SDL_SCANCODE_X; 153 | io.KeyMap[ImGuiKey_Y] = SDL_SCANCODE_Y; 154 | io.KeyMap[ImGuiKey_Z] = SDL_SCANCODE_Z; 155 | 156 | io.SetClipboardTextFn = ImGui_ImplSDL2_SetClipboardText; 157 | io.GetClipboardTextFn = ImGui_ImplSDL2_GetClipboardText; 158 | io.ClipboardUserData = NULL; 159 | 160 | g_MouseCursors[ImGuiMouseCursor_Arrow] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW); 161 | g_MouseCursors[ImGuiMouseCursor_TextInput] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_IBEAM); 162 | g_MouseCursors[ImGuiMouseCursor_ResizeAll] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEALL); 163 | g_MouseCursors[ImGuiMouseCursor_ResizeNS] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENS); 164 | g_MouseCursors[ImGuiMouseCursor_ResizeEW] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEWE); 165 | g_MouseCursors[ImGuiMouseCursor_ResizeNESW] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENESW); 166 | g_MouseCursors[ImGuiMouseCursor_ResizeNWSE] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENWSE); 167 | g_MouseCursors[ImGuiMouseCursor_Hand] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_HAND); 168 | 169 | #ifdef _WIN32 170 | SDL_SysWMinfo wmInfo; 171 | SDL_VERSION(&wmInfo.version); 172 | SDL_GetWindowWMInfo(window, &wmInfo); 173 | io.ImeWindowHandle = wmInfo.info.win.window; 174 | #else 175 | (void)window; 176 | #endif 177 | 178 | return true; 179 | } 180 | 181 | bool ImGui_ImplSDL2_InitForOpenGL(SDL_Window* window, void* sdl_gl_context) 182 | { 183 | (void)sdl_gl_context; // Viewport branch will need this. 184 | return ImGui_ImplSDL2_Init(window); 185 | } 186 | 187 | bool ImGui_ImplSDL2_InitForVulkan(SDL_Window* window) 188 | { 189 | #if !SDL_HAS_VULKAN 190 | IM_ASSERT(0 && "Unsupported"); 191 | #endif 192 | return ImGui_ImplSDL2_Init(window); 193 | } 194 | 195 | bool ImGui_ImplSDL2_InitForD3D(SDL_Window* window) 196 | { 197 | #if !defined(_WIN32) 198 | IM_ASSERT(0 && "Unsupported"); 199 | #endif 200 | return ImGui_ImplSDL2_Init(window); 201 | } 202 | 203 | void ImGui_ImplSDL2_Shutdown() 204 | { 205 | g_Window = NULL; 206 | 207 | // Destroy last known clipboard data 208 | if (g_ClipboardTextData) 209 | SDL_free(g_ClipboardTextData); 210 | g_ClipboardTextData = NULL; 211 | 212 | // Destroy SDL mouse cursors 213 | for (ImGuiMouseCursor cursor_n = 0; cursor_n < ImGuiMouseCursor_COUNT; cursor_n++) 214 | SDL_FreeCursor(g_MouseCursors[cursor_n]); 215 | memset(g_MouseCursors, 0, sizeof(g_MouseCursors)); 216 | } 217 | 218 | static void ImGui_ImplSDL2_UpdateMousePosAndButtons() 219 | { 220 | ImGuiIO& io = ImGui::GetIO(); 221 | 222 | // Set OS mouse position if requested (rarely used, only when ImGuiConfigFlags_NavEnableSetMousePos is enabled by user) 223 | if (io.WantSetMousePos) 224 | SDL_WarpMouseInWindow(g_Window, (int)io.MousePos.x, (int)io.MousePos.y); 225 | else 226 | io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX); 227 | 228 | int mx, my; 229 | Uint32 mouse_buttons = SDL_GetMouseState(&mx, &my); 230 | io.MouseDown[0] = g_MousePressed[0] || (mouse_buttons & SDL_BUTTON(SDL_BUTTON_LEFT)) != 0; // If a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame. 231 | io.MouseDown[1] = g_MousePressed[1] || (mouse_buttons & SDL_BUTTON(SDL_BUTTON_RIGHT)) != 0; 232 | io.MouseDown[2] = g_MousePressed[2] || (mouse_buttons & SDL_BUTTON(SDL_BUTTON_MIDDLE)) != 0; 233 | g_MousePressed[0] = g_MousePressed[1] = g_MousePressed[2] = false; 234 | 235 | #if SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE && !defined(__EMSCRIPTEN__) && !defined(__ANDROID__) && !(defined(__APPLE__) && TARGET_OS_IOS) 236 | SDL_Window* focused_window = SDL_GetKeyboardFocus(); 237 | if (g_Window == focused_window) 238 | { 239 | // SDL_GetMouseState() gives mouse position seemingly based on the last window entered/focused(?) 240 | // The creation of a new windows at runtime and SDL_CaptureMouse both seems to severely mess up with that, so we retrieve that position globally. 241 | int wx, wy; 242 | SDL_GetWindowPosition(focused_window, &wx, &wy); 243 | SDL_GetGlobalMouseState(&mx, &my); 244 | mx -= wx; 245 | my -= wy; 246 | io.MousePos = ImVec2((float)mx, (float)my); 247 | } 248 | 249 | // SDL_CaptureMouse() let the OS know e.g. that our imgui drag outside the SDL window boundaries shouldn't e.g. trigger the OS window resize cursor. 250 | // The function is only supported from SDL 2.0.4 (released Jan 2016) 251 | bool any_mouse_button_down = ImGui::IsAnyMouseDown(); 252 | SDL_CaptureMouse(any_mouse_button_down ? SDL_TRUE : SDL_FALSE); 253 | #else 254 | if (SDL_GetWindowFlags(g_Window) & SDL_WINDOW_INPUT_FOCUS) 255 | io.MousePos = ImVec2((float)mx, (float)my); 256 | #endif 257 | } 258 | 259 | static void ImGui_ImplSDL2_UpdateMouseCursor() 260 | { 261 | ImGuiIO& io = ImGui::GetIO(); 262 | if (io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange) 263 | return; 264 | 265 | ImGuiMouseCursor imgui_cursor = ImGui::GetMouseCursor(); 266 | if (io.MouseDrawCursor || imgui_cursor == ImGuiMouseCursor_None) 267 | { 268 | // Hide OS mouse cursor if imgui is drawing it or if it wants no cursor 269 | SDL_ShowCursor(SDL_FALSE); 270 | } 271 | else 272 | { 273 | // Show OS mouse cursor 274 | SDL_SetCursor(g_MouseCursors[imgui_cursor] ? g_MouseCursors[imgui_cursor] : g_MouseCursors[ImGuiMouseCursor_Arrow]); 275 | SDL_ShowCursor(SDL_TRUE); 276 | } 277 | } 278 | 279 | static void ImGui_ImplSDL2_UpdateGamepads() 280 | { 281 | ImGuiIO& io = ImGui::GetIO(); 282 | memset(io.NavInputs, 0, sizeof(io.NavInputs)); 283 | if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) == 0) 284 | return; 285 | 286 | // Get gamepad 287 | SDL_GameController* game_controller = SDL_GameControllerOpen(0); 288 | if (!game_controller) 289 | { 290 | io.BackendFlags &= ~ImGuiBackendFlags_HasGamepad; 291 | return; 292 | } 293 | 294 | // Update gamepad inputs 295 | #define MAP_BUTTON(NAV_NO, BUTTON_NO) { io.NavInputs[NAV_NO] = (SDL_GameControllerGetButton(game_controller, BUTTON_NO) != 0) ? 1.0f : 0.0f; } 296 | #define MAP_ANALOG(NAV_NO, AXIS_NO, V0, V1) { float vn = (float)(SDL_GameControllerGetAxis(game_controller, AXIS_NO) - V0) / (float)(V1 - V0); if (vn > 1.0f) vn = 1.0f; if (vn > 0.0f && io.NavInputs[NAV_NO] < vn) io.NavInputs[NAV_NO] = vn; } 297 | const int thumb_dead_zone = 8000; // SDL_gamecontroller.h suggests using this value. 298 | MAP_BUTTON(ImGuiNavInput_Activate, SDL_CONTROLLER_BUTTON_A); // Cross / A 299 | MAP_BUTTON(ImGuiNavInput_Cancel, SDL_CONTROLLER_BUTTON_B); // Circle / B 300 | MAP_BUTTON(ImGuiNavInput_Menu, SDL_CONTROLLER_BUTTON_X); // Square / X 301 | MAP_BUTTON(ImGuiNavInput_Input, SDL_CONTROLLER_BUTTON_Y); // Triangle / Y 302 | MAP_BUTTON(ImGuiNavInput_DpadLeft, SDL_CONTROLLER_BUTTON_DPAD_LEFT); // D-Pad Left 303 | MAP_BUTTON(ImGuiNavInput_DpadRight, SDL_CONTROLLER_BUTTON_DPAD_RIGHT); // D-Pad Right 304 | MAP_BUTTON(ImGuiNavInput_DpadUp, SDL_CONTROLLER_BUTTON_DPAD_UP); // D-Pad Up 305 | MAP_BUTTON(ImGuiNavInput_DpadDown, SDL_CONTROLLER_BUTTON_DPAD_DOWN); // D-Pad Down 306 | MAP_BUTTON(ImGuiNavInput_FocusPrev, SDL_CONTROLLER_BUTTON_LEFTSHOULDER); // L1 / LB 307 | MAP_BUTTON(ImGuiNavInput_FocusNext, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER); // R1 / RB 308 | MAP_BUTTON(ImGuiNavInput_TweakSlow, SDL_CONTROLLER_BUTTON_LEFTSHOULDER); // L1 / LB 309 | MAP_BUTTON(ImGuiNavInput_TweakFast, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER); // R1 / RB 310 | MAP_ANALOG(ImGuiNavInput_LStickLeft, SDL_CONTROLLER_AXIS_LEFTX, -thumb_dead_zone, -32768); 311 | MAP_ANALOG(ImGuiNavInput_LStickRight, SDL_CONTROLLER_AXIS_LEFTX, +thumb_dead_zone, +32767); 312 | MAP_ANALOG(ImGuiNavInput_LStickUp, SDL_CONTROLLER_AXIS_LEFTY, -thumb_dead_zone, -32767); 313 | MAP_ANALOG(ImGuiNavInput_LStickDown, SDL_CONTROLLER_AXIS_LEFTY, +thumb_dead_zone, +32767); 314 | 315 | io.BackendFlags |= ImGuiBackendFlags_HasGamepad; 316 | #undef MAP_BUTTON 317 | #undef MAP_ANALOG 318 | } 319 | 320 | void ImGui_ImplSDL2_NewFrame(SDL_Window* window) 321 | { 322 | ImGuiIO& io = ImGui::GetIO(); 323 | IM_ASSERT(io.Fonts->IsBuilt() && "Font atlas not built! It is generally built by the renderer back-end. Missing call to renderer _NewFrame() function? e.g. ImGui_ImplOpenGL3_NewFrame()."); 324 | 325 | // Setup display size (every frame to accommodate for window resizing) 326 | int w, h; 327 | int display_w, display_h; 328 | SDL_GetWindowSize(window, &w, &h); 329 | SDL_GL_GetDrawableSize(window, &display_w, &display_h); 330 | io.DisplaySize = ImVec2((float)w, (float)h); 331 | if (w > 0 && h > 0) 332 | io.DisplayFramebufferScale = ImVec2((float)display_w / w, (float)display_h / h); 333 | 334 | // Setup time step (we don't use SDL_GetTicks() because it is using millisecond resolution) 335 | static Uint64 frequency = SDL_GetPerformanceFrequency(); 336 | Uint64 current_time = SDL_GetPerformanceCounter(); 337 | io.DeltaTime = g_Time > 0 ? (float)((double)(current_time - g_Time) / frequency) : (float)(1.0f / 60.0f); 338 | g_Time = current_time; 339 | 340 | ImGui_ImplSDL2_UpdateMousePosAndButtons(); 341 | ImGui_ImplSDL2_UpdateMouseCursor(); 342 | 343 | // Update game controllers (if enabled and available) 344 | ImGui_ImplSDL2_UpdateGamepads(); 345 | } 346 | -------------------------------------------------------------------------------- /TinyEngine/include/imgui/imgui_impl_sdl.h: -------------------------------------------------------------------------------- 1 | // dear imgui: Platform Binding for SDL2 2 | // This needs to be used along with a Renderer (e.g. DirectX11, OpenGL3, Vulkan..) 3 | // (Info: SDL2 is a cross-platform general purpose library for handling windows, inputs, graphics context creation, etc.) 4 | 5 | // Implemented features: 6 | // [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. 7 | // [X] Platform: Clipboard support. 8 | // [X] Platform: Keyboard arrays indexed using SDL_SCANCODE_* codes, e.g. ImGui::IsKeyPressed(SDL_SCANCODE_SPACE). 9 | // [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'. 10 | // Missing features: 11 | // [ ] Platform: SDL2 handling of IME under Windows appears to be broken and it explicitly disable the regular Windows IME. You can restore Windows IME by compiling SDL with SDL_DISABLE_WINDOWS_IME. 12 | 13 | // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. 14 | // If you are new to dear imgui, read examples/README.txt and read the documentation at the top of imgui.cpp. 15 | // https://github.com/ocornut/imgui 16 | 17 | #pragma once 18 | 19 | struct SDL_Window; 20 | typedef union SDL_Event SDL_Event; 21 | 22 | IMGUI_IMPL_API bool ImGui_ImplSDL2_InitForOpenGL(SDL_Window* window, void* sdl_gl_context); 23 | IMGUI_IMPL_API bool ImGui_ImplSDL2_InitForVulkan(SDL_Window* window); 24 | IMGUI_IMPL_API bool ImGui_ImplSDL2_InitForD3D(SDL_Window* window); 25 | IMGUI_IMPL_API void ImGui_ImplSDL2_Shutdown(); 26 | IMGUI_IMPL_API void ImGui_ImplSDL2_NewFrame(SDL_Window* window); 27 | IMGUI_IMPL_API bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event); 28 | -------------------------------------------------------------------------------- /TinyEngine/include/imgui/imstb_rectpack.h: -------------------------------------------------------------------------------- 1 | // [DEAR IMGUI] 2 | // This is a slightly modified version of stb_rect_pack.h 0.99. 3 | // Those changes would need to be pushed into nothings/stb: 4 | // - Added STBRP__CDECL 5 | // Grep for [DEAR IMGUI] to find the changes. 6 | 7 | // stb_rect_pack.h - v0.99 - public domain - rectangle packing 8 | // Sean Barrett 2014 9 | // 10 | // Useful for e.g. packing rectangular textures into an atlas. 11 | // Does not do rotation. 12 | // 13 | // Not necessarily the awesomest packing method, but better than 14 | // the totally naive one in stb_truetype (which is primarily what 15 | // this is meant to replace). 16 | // 17 | // Has only had a few tests run, may have issues. 18 | // 19 | // More docs to come. 20 | // 21 | // No memory allocations; uses qsort() and assert() from stdlib. 22 | // Can override those by defining STBRP_SORT and STBRP_ASSERT. 23 | // 24 | // This library currently uses the Skyline Bottom-Left algorithm. 25 | // 26 | // Please note: better rectangle packers are welcome! Please 27 | // implement them to the same API, but with a different init 28 | // function. 29 | // 30 | // Credits 31 | // 32 | // Library 33 | // Sean Barrett 34 | // Minor features 35 | // Martins Mozeiko 36 | // github:IntellectualKitty 37 | // 38 | // Bugfixes / warning fixes 39 | // Jeremy Jaussaud 40 | // 41 | // Version history: 42 | // 43 | // 0.99 (2019-02-07) warning fixes 44 | // 0.11 (2017-03-03) return packing success/fail result 45 | // 0.10 (2016-10-25) remove cast-away-const to avoid warnings 46 | // 0.09 (2016-08-27) fix compiler warnings 47 | // 0.08 (2015-09-13) really fix bug with empty rects (w=0 or h=0) 48 | // 0.07 (2015-09-13) fix bug with empty rects (w=0 or h=0) 49 | // 0.06 (2015-04-15) added STBRP_SORT to allow replacing qsort 50 | // 0.05: added STBRP_ASSERT to allow replacing assert 51 | // 0.04: fixed minor bug in STBRP_LARGE_RECTS support 52 | // 0.01: initial release 53 | // 54 | // LICENSE 55 | // 56 | // See end of file for license information. 57 | 58 | ////////////////////////////////////////////////////////////////////////////// 59 | // 60 | // INCLUDE SECTION 61 | // 62 | 63 | #ifndef STB_INCLUDE_STB_RECT_PACK_H 64 | #define STB_INCLUDE_STB_RECT_PACK_H 65 | 66 | #define STB_RECT_PACK_VERSION 1 67 | 68 | #ifdef STBRP_STATIC 69 | #define STBRP_DEF static 70 | #else 71 | #define STBRP_DEF extern 72 | #endif 73 | 74 | #ifdef __cplusplus 75 | extern "C" { 76 | #endif 77 | 78 | typedef struct stbrp_context stbrp_context; 79 | typedef struct stbrp_node stbrp_node; 80 | typedef struct stbrp_rect stbrp_rect; 81 | 82 | #ifdef STBRP_LARGE_RECTS 83 | typedef int stbrp_coord; 84 | #else 85 | typedef unsigned short stbrp_coord; 86 | #endif 87 | 88 | STBRP_DEF int stbrp_pack_rects (stbrp_context *context, stbrp_rect *rects, int num_rects); 89 | // Assign packed locations to rectangles. The rectangles are of type 90 | // 'stbrp_rect' defined below, stored in the array 'rects', and there 91 | // are 'num_rects' many of them. 92 | // 93 | // Rectangles which are successfully packed have the 'was_packed' flag 94 | // set to a non-zero value and 'x' and 'y' store the minimum location 95 | // on each axis (i.e. bottom-left in cartesian coordinates, top-left 96 | // if you imagine y increasing downwards). Rectangles which do not fit 97 | // have the 'was_packed' flag set to 0. 98 | // 99 | // You should not try to access the 'rects' array from another thread 100 | // while this function is running, as the function temporarily reorders 101 | // the array while it executes. 102 | // 103 | // To pack into another rectangle, you need to call stbrp_init_target 104 | // again. To continue packing into the same rectangle, you can call 105 | // this function again. Calling this multiple times with multiple rect 106 | // arrays will probably produce worse packing results than calling it 107 | // a single time with the full rectangle array, but the option is 108 | // available. 109 | // 110 | // The function returns 1 if all of the rectangles were successfully 111 | // packed and 0 otherwise. 112 | 113 | struct stbrp_rect 114 | { 115 | // reserved for your use: 116 | int id; 117 | 118 | // input: 119 | stbrp_coord w, h; 120 | 121 | // output: 122 | stbrp_coord x, y; 123 | int was_packed; // non-zero if valid packing 124 | 125 | }; // 16 bytes, nominally 126 | 127 | 128 | STBRP_DEF void stbrp_init_target (stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes); 129 | // Initialize a rectangle packer to: 130 | // pack a rectangle that is 'width' by 'height' in dimensions 131 | // using temporary storage provided by the array 'nodes', which is 'num_nodes' long 132 | // 133 | // You must call this function every time you start packing into a new target. 134 | // 135 | // There is no "shutdown" function. The 'nodes' memory must stay valid for 136 | // the following stbrp_pack_rects() call (or calls), but can be freed after 137 | // the call (or calls) finish. 138 | // 139 | // Note: to guarantee best results, either: 140 | // 1. make sure 'num_nodes' >= 'width' 141 | // or 2. call stbrp_allow_out_of_mem() defined below with 'allow_out_of_mem = 1' 142 | // 143 | // If you don't do either of the above things, widths will be quantized to multiples 144 | // of small integers to guarantee the algorithm doesn't run out of temporary storage. 145 | // 146 | // If you do #2, then the non-quantized algorithm will be used, but the algorithm 147 | // may run out of temporary storage and be unable to pack some rectangles. 148 | 149 | STBRP_DEF void stbrp_setup_allow_out_of_mem (stbrp_context *context, int allow_out_of_mem); 150 | // Optionally call this function after init but before doing any packing to 151 | // change the handling of the out-of-temp-memory scenario, described above. 152 | // If you call init again, this will be reset to the default (false). 153 | 154 | 155 | STBRP_DEF void stbrp_setup_heuristic (stbrp_context *context, int heuristic); 156 | // Optionally select which packing heuristic the library should use. Different 157 | // heuristics will produce better/worse results for different data sets. 158 | // If you call init again, this will be reset to the default. 159 | 160 | enum 161 | { 162 | STBRP_HEURISTIC_Skyline_default=0, 163 | STBRP_HEURISTIC_Skyline_BL_sortHeight = STBRP_HEURISTIC_Skyline_default, 164 | STBRP_HEURISTIC_Skyline_BF_sortHeight 165 | }; 166 | 167 | 168 | ////////////////////////////////////////////////////////////////////////////// 169 | // 170 | // the details of the following structures don't matter to you, but they must 171 | // be visible so you can handle the memory allocations for them 172 | 173 | struct stbrp_node 174 | { 175 | stbrp_coord x,y; 176 | stbrp_node *next; 177 | }; 178 | 179 | struct stbrp_context 180 | { 181 | int width; 182 | int height; 183 | int align; 184 | int init_mode; 185 | int heuristic; 186 | int num_nodes; 187 | stbrp_node *active_head; 188 | stbrp_node *free_head; 189 | stbrp_node extra[2]; // we allocate two extra nodes so optimal user-node-count is 'width' not 'width+2' 190 | }; 191 | 192 | #ifdef __cplusplus 193 | } 194 | #endif 195 | 196 | #endif 197 | 198 | ////////////////////////////////////////////////////////////////////////////// 199 | // 200 | // IMPLEMENTATION SECTION 201 | // 202 | 203 | #ifdef STB_RECT_PACK_IMPLEMENTATION 204 | #ifndef STBRP_SORT 205 | #include 206 | #define STBRP_SORT qsort 207 | #endif 208 | 209 | #ifndef STBRP_ASSERT 210 | #include 211 | #define STBRP_ASSERT assert 212 | #endif 213 | 214 | // [DEAR IMGUI] Added STBRP__CDECL 215 | #ifdef _MSC_VER 216 | #define STBRP__NOTUSED(v) (void)(v) 217 | #define STBRP__CDECL __cdecl 218 | #else 219 | #define STBRP__NOTUSED(v) (void)sizeof(v) 220 | #define STBRP__CDECL 221 | #endif 222 | 223 | enum 224 | { 225 | STBRP__INIT_skyline = 1 226 | }; 227 | 228 | STBRP_DEF void stbrp_setup_heuristic(stbrp_context *context, int heuristic) 229 | { 230 | switch (context->init_mode) { 231 | case STBRP__INIT_skyline: 232 | STBRP_ASSERT(heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight || heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight); 233 | context->heuristic = heuristic; 234 | break; 235 | default: 236 | STBRP_ASSERT(0); 237 | } 238 | } 239 | 240 | STBRP_DEF void stbrp_setup_allow_out_of_mem(stbrp_context *context, int allow_out_of_mem) 241 | { 242 | if (allow_out_of_mem) 243 | // if it's ok to run out of memory, then don't bother aligning them; 244 | // this gives better packing, but may fail due to OOM (even though 245 | // the rectangles easily fit). @TODO a smarter approach would be to only 246 | // quantize once we've hit OOM, then we could get rid of this parameter. 247 | context->align = 1; 248 | else { 249 | // if it's not ok to run out of memory, then quantize the widths 250 | // so that num_nodes is always enough nodes. 251 | // 252 | // I.e. num_nodes * align >= width 253 | // align >= width / num_nodes 254 | // align = ceil(width/num_nodes) 255 | 256 | context->align = (context->width + context->num_nodes-1) / context->num_nodes; 257 | } 258 | } 259 | 260 | STBRP_DEF void stbrp_init_target(stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes) 261 | { 262 | int i; 263 | #ifndef STBRP_LARGE_RECTS 264 | STBRP_ASSERT(width <= 0xffff && height <= 0xffff); 265 | #endif 266 | 267 | for (i=0; i < num_nodes-1; ++i) 268 | nodes[i].next = &nodes[i+1]; 269 | nodes[i].next = NULL; 270 | context->init_mode = STBRP__INIT_skyline; 271 | context->heuristic = STBRP_HEURISTIC_Skyline_default; 272 | context->free_head = &nodes[0]; 273 | context->active_head = &context->extra[0]; 274 | context->width = width; 275 | context->height = height; 276 | context->num_nodes = num_nodes; 277 | stbrp_setup_allow_out_of_mem(context, 0); 278 | 279 | // node 0 is the full width, node 1 is the sentinel (lets us not store width explicitly) 280 | context->extra[0].x = 0; 281 | context->extra[0].y = 0; 282 | context->extra[0].next = &context->extra[1]; 283 | context->extra[1].x = (stbrp_coord) width; 284 | #ifdef STBRP_LARGE_RECTS 285 | context->extra[1].y = (1<<30); 286 | #else 287 | context->extra[1].y = 65535; 288 | #endif 289 | context->extra[1].next = NULL; 290 | } 291 | 292 | // find minimum y position if it starts at x1 293 | static int stbrp__skyline_find_min_y(stbrp_context *c, stbrp_node *first, int x0, int width, int *pwaste) 294 | { 295 | stbrp_node *node = first; 296 | int x1 = x0 + width; 297 | int min_y, visited_width, waste_area; 298 | 299 | STBRP__NOTUSED(c); 300 | 301 | STBRP_ASSERT(first->x <= x0); 302 | 303 | #if 0 304 | // skip in case we're past the node 305 | while (node->next->x <= x0) 306 | ++node; 307 | #else 308 | STBRP_ASSERT(node->next->x > x0); // we ended up handling this in the caller for efficiency 309 | #endif 310 | 311 | STBRP_ASSERT(node->x <= x0); 312 | 313 | min_y = 0; 314 | waste_area = 0; 315 | visited_width = 0; 316 | while (node->x < x1) { 317 | if (node->y > min_y) { 318 | // raise min_y higher. 319 | // we've accounted for all waste up to min_y, 320 | // but we'll now add more waste for everything we've visted 321 | waste_area += visited_width * (node->y - min_y); 322 | min_y = node->y; 323 | // the first time through, visited_width might be reduced 324 | if (node->x < x0) 325 | visited_width += node->next->x - x0; 326 | else 327 | visited_width += node->next->x - node->x; 328 | } else { 329 | // add waste area 330 | int under_width = node->next->x - node->x; 331 | if (under_width + visited_width > width) 332 | under_width = width - visited_width; 333 | waste_area += under_width * (min_y - node->y); 334 | visited_width += under_width; 335 | } 336 | node = node->next; 337 | } 338 | 339 | *pwaste = waste_area; 340 | return min_y; 341 | } 342 | 343 | typedef struct 344 | { 345 | int x,y; 346 | stbrp_node **prev_link; 347 | } stbrp__findresult; 348 | 349 | static stbrp__findresult stbrp__skyline_find_best_pos(stbrp_context *c, int width, int height) 350 | { 351 | int best_waste = (1<<30), best_x, best_y = (1 << 30); 352 | stbrp__findresult fr; 353 | stbrp_node **prev, *node, *tail, **best = NULL; 354 | 355 | // align to multiple of c->align 356 | width = (width + c->align - 1); 357 | width -= width % c->align; 358 | STBRP_ASSERT(width % c->align == 0); 359 | 360 | node = c->active_head; 361 | prev = &c->active_head; 362 | while (node->x + width <= c->width) { 363 | int y,waste; 364 | y = stbrp__skyline_find_min_y(c, node, node->x, width, &waste); 365 | if (c->heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight) { // actually just want to test BL 366 | // bottom left 367 | if (y < best_y) { 368 | best_y = y; 369 | best = prev; 370 | } 371 | } else { 372 | // best-fit 373 | if (y + height <= c->height) { 374 | // can only use it if it first vertically 375 | if (y < best_y || (y == best_y && waste < best_waste)) { 376 | best_y = y; 377 | best_waste = waste; 378 | best = prev; 379 | } 380 | } 381 | } 382 | prev = &node->next; 383 | node = node->next; 384 | } 385 | 386 | best_x = (best == NULL) ? 0 : (*best)->x; 387 | 388 | // if doing best-fit (BF), we also have to try aligning right edge to each node position 389 | // 390 | // e.g, if fitting 391 | // 392 | // ____________________ 393 | // |____________________| 394 | // 395 | // into 396 | // 397 | // | | 398 | // | ____________| 399 | // |____________| 400 | // 401 | // then right-aligned reduces waste, but bottom-left BL is always chooses left-aligned 402 | // 403 | // This makes BF take about 2x the time 404 | 405 | if (c->heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight) { 406 | tail = c->active_head; 407 | node = c->active_head; 408 | prev = &c->active_head; 409 | // find first node that's admissible 410 | while (tail->x < width) 411 | tail = tail->next; 412 | while (tail) { 413 | int xpos = tail->x - width; 414 | int y,waste; 415 | STBRP_ASSERT(xpos >= 0); 416 | // find the left position that matches this 417 | while (node->next->x <= xpos) { 418 | prev = &node->next; 419 | node = node->next; 420 | } 421 | STBRP_ASSERT(node->next->x > xpos && node->x <= xpos); 422 | y = stbrp__skyline_find_min_y(c, node, xpos, width, &waste); 423 | if (y + height < c->height) { 424 | if (y <= best_y) { 425 | if (y < best_y || waste < best_waste || (waste==best_waste && xpos < best_x)) { 426 | best_x = xpos; 427 | STBRP_ASSERT(y <= best_y); 428 | best_y = y; 429 | best_waste = waste; 430 | best = prev; 431 | } 432 | } 433 | } 434 | tail = tail->next; 435 | } 436 | } 437 | 438 | fr.prev_link = best; 439 | fr.x = best_x; 440 | fr.y = best_y; 441 | return fr; 442 | } 443 | 444 | static stbrp__findresult stbrp__skyline_pack_rectangle(stbrp_context *context, int width, int height) 445 | { 446 | // find best position according to heuristic 447 | stbrp__findresult res = stbrp__skyline_find_best_pos(context, width, height); 448 | stbrp_node *node, *cur; 449 | 450 | // bail if: 451 | // 1. it failed 452 | // 2. the best node doesn't fit (we don't always check this) 453 | // 3. we're out of memory 454 | if (res.prev_link == NULL || res.y + height > context->height || context->free_head == NULL) { 455 | res.prev_link = NULL; 456 | return res; 457 | } 458 | 459 | // on success, create new node 460 | node = context->free_head; 461 | node->x = (stbrp_coord) res.x; 462 | node->y = (stbrp_coord) (res.y + height); 463 | 464 | context->free_head = node->next; 465 | 466 | // insert the new node into the right starting point, and 467 | // let 'cur' point to the remaining nodes needing to be 468 | // stiched back in 469 | 470 | cur = *res.prev_link; 471 | if (cur->x < res.x) { 472 | // preserve the existing one, so start testing with the next one 473 | stbrp_node *next = cur->next; 474 | cur->next = node; 475 | cur = next; 476 | } else { 477 | *res.prev_link = node; 478 | } 479 | 480 | // from here, traverse cur and free the nodes, until we get to one 481 | // that shouldn't be freed 482 | while (cur->next && cur->next->x <= res.x + width) { 483 | stbrp_node *next = cur->next; 484 | // move the current node to the free list 485 | cur->next = context->free_head; 486 | context->free_head = cur; 487 | cur = next; 488 | } 489 | 490 | // stitch the list back in 491 | node->next = cur; 492 | 493 | if (cur->x < res.x + width) 494 | cur->x = (stbrp_coord) (res.x + width); 495 | 496 | #ifdef _DEBUG 497 | cur = context->active_head; 498 | while (cur->x < context->width) { 499 | STBRP_ASSERT(cur->x < cur->next->x); 500 | cur = cur->next; 501 | } 502 | STBRP_ASSERT(cur->next == NULL); 503 | 504 | { 505 | int count=0; 506 | cur = context->active_head; 507 | while (cur) { 508 | cur = cur->next; 509 | ++count; 510 | } 511 | cur = context->free_head; 512 | while (cur) { 513 | cur = cur->next; 514 | ++count; 515 | } 516 | STBRP_ASSERT(count == context->num_nodes+2); 517 | } 518 | #endif 519 | 520 | return res; 521 | } 522 | 523 | // [DEAR IMGUI] Added STBRP__CDECL 524 | static int STBRP__CDECL rect_height_compare(const void *a, const void *b) 525 | { 526 | const stbrp_rect *p = (const stbrp_rect *) a; 527 | const stbrp_rect *q = (const stbrp_rect *) b; 528 | if (p->h > q->h) 529 | return -1; 530 | if (p->h < q->h) 531 | return 1; 532 | return (p->w > q->w) ? -1 : (p->w < q->w); 533 | } 534 | 535 | // [DEAR IMGUI] Added STBRP__CDECL 536 | static int STBRP__CDECL rect_original_order(const void *a, const void *b) 537 | { 538 | const stbrp_rect *p = (const stbrp_rect *) a; 539 | const stbrp_rect *q = (const stbrp_rect *) b; 540 | return (p->was_packed < q->was_packed) ? -1 : (p->was_packed > q->was_packed); 541 | } 542 | 543 | #ifdef STBRP_LARGE_RECTS 544 | #define STBRP__MAXVAL 0xffffffff 545 | #else 546 | #define STBRP__MAXVAL 0xffff 547 | #endif 548 | 549 | STBRP_DEF int stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int num_rects) 550 | { 551 | int i, all_rects_packed = 1; 552 | 553 | // we use the 'was_packed' field internally to allow sorting/unsorting 554 | for (i=0; i < num_rects; ++i) { 555 | rects[i].was_packed = i; 556 | } 557 | 558 | // sort according to heuristic 559 | STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_height_compare); 560 | 561 | for (i=0; i < num_rects; ++i) { 562 | if (rects[i].w == 0 || rects[i].h == 0) { 563 | rects[i].x = rects[i].y = 0; // empty rect needs no space 564 | } else { 565 | stbrp__findresult fr = stbrp__skyline_pack_rectangle(context, rects[i].w, rects[i].h); 566 | if (fr.prev_link) { 567 | rects[i].x = (stbrp_coord) fr.x; 568 | rects[i].y = (stbrp_coord) fr.y; 569 | } else { 570 | rects[i].x = rects[i].y = STBRP__MAXVAL; 571 | } 572 | } 573 | } 574 | 575 | // unsort 576 | STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_original_order); 577 | 578 | // set was_packed flags and all_rects_packed status 579 | for (i=0; i < num_rects; ++i) { 580 | rects[i].was_packed = !(rects[i].x == STBRP__MAXVAL && rects[i].y == STBRP__MAXVAL); 581 | if (!rects[i].was_packed) 582 | all_rects_packed = 0; 583 | } 584 | 585 | // return the all_rects_packed status 586 | return all_rects_packed; 587 | } 588 | #endif 589 | 590 | /* 591 | ------------------------------------------------------------------------------ 592 | This software is available under 2 licenses -- choose whichever you prefer. 593 | ------------------------------------------------------------------------------ 594 | ALTERNATIVE A - MIT License 595 | Copyright (c) 2017 Sean Barrett 596 | Permission is hereby granted, free of charge, to any person obtaining a copy of 597 | this software and associated documentation files (the "Software"), to deal in 598 | the Software without restriction, including without limitation the rights to 599 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 600 | of the Software, and to permit persons to whom the Software is furnished to do 601 | so, subject to the following conditions: 602 | The above copyright notice and this permission notice shall be included in all 603 | copies or substantial portions of the Software. 604 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 605 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 606 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 607 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 608 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 609 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 610 | SOFTWARE. 611 | ------------------------------------------------------------------------------ 612 | ALTERNATIVE B - Public Domain (www.unlicense.org) 613 | This is free and unencumbered software released into the public domain. 614 | Anyone is free to copy, modify, publish, use, compile, sell, or distribute this 615 | software, either in source code form or as a compiled binary, for any purpose, 616 | commercial or non-commercial, and by any means. 617 | In jurisdictions that recognize copyright laws, the author or authors of this 618 | software dedicate any and all copyright interest in the software to the public 619 | domain. We make this dedication for the benefit of the public at large and to 620 | the detriment of our heirs and successors. We intend this dedication to be an 621 | overt act of relinquishment in perpetuity of all present and future rights to 622 | this software under copyright law. 623 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 624 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 625 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 626 | AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 627 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 628 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 629 | ------------------------------------------------------------------------------ 630 | */ 631 | -------------------------------------------------------------------------------- /TinyEngine/include/imgui/misc/README.txt: -------------------------------------------------------------------------------- 1 | 2 | misc/cpp/ 3 | InputText() wrappers for C++ standard library (STL) type: std::string. 4 | This is also an example of how you may wrap your own similar types. 5 | 6 | misc/fonts/ 7 | Fonts loading/merging instructions (e.g. How to handle glyph ranges, how to merge icons fonts). 8 | Command line tool "binary_to_compressed_c" to create compressed arrays to embed data in source code. 9 | Suggested fonts and links. 10 | 11 | misc/freetype/ 12 | Font atlas builder/rasterizer using FreeType instead of stb_truetype. 13 | Benefit from better FreeType rasterization, in particular for small fonts. 14 | 15 | misc/natvis/ 16 | Natvis file to describe dear imgui types in the Visual Studio debugger. 17 | With this, types like ImVector<> will be displayed nicely in the debugger. 18 | You can include this file a Visual Studio project file, or install it in Visual Studio folder. 19 | -------------------------------------------------------------------------------- /TinyEngine/include/imgui/misc/cpp/README.txt: -------------------------------------------------------------------------------- 1 | 2 | imgui_stdlib.h + imgui_stdlib.cpp 3 | InputText() wrappers for C++ standard library (STL) type: std::string. 4 | This is also an example of how you may wrap your own similar types. 5 | 6 | imgui_scoped.h 7 | [Experimental, not currently in main repository] 8 | Additional header file with some RAII-style wrappers for common Dear ImGui functions. 9 | Try by merging: https://github.com/ocornut/imgui/pull/2197 10 | Discuss at: https://github.com/ocornut/imgui/issues/2096 11 | -------------------------------------------------------------------------------- /TinyEngine/include/imgui/misc/cpp/imgui_stdlib.cpp: -------------------------------------------------------------------------------- 1 | // imgui_stdlib.cpp 2 | // Wrappers for C++ standard library (STL) types (std::string, etc.) 3 | // This is also an example of how you may wrap your own similar types. 4 | 5 | // Compatibility: 6 | // - std::string support is only guaranteed to work from C++11. 7 | // If you try to use it pre-C++11, please share your findings (w/ info about compiler/architecture) 8 | 9 | // Changelog: 10 | // - v0.10: Initial version. Added InputText() / InputTextMultiline() calls with std::string 11 | 12 | #include "imgui.h" 13 | #include "imgui_stdlib.h" 14 | 15 | struct InputTextCallback_UserData 16 | { 17 | std::string* Str; 18 | ImGuiInputTextCallback ChainCallback; 19 | void* ChainCallbackUserData; 20 | }; 21 | 22 | static int InputTextCallback(ImGuiInputTextCallbackData* data) 23 | { 24 | InputTextCallback_UserData* user_data = (InputTextCallback_UserData*)data->UserData; 25 | if (data->EventFlag == ImGuiInputTextFlags_CallbackResize) 26 | { 27 | // Resize string callback 28 | // If for some reason we refuse the new length (BufTextLen) and/or capacity (BufSize) we need to set them back to what we want. 29 | std::string* str = user_data->Str; 30 | IM_ASSERT(data->Buf == str->c_str()); 31 | str->resize(data->BufTextLen); 32 | data->Buf = (char*)str->c_str(); 33 | } 34 | else if (user_data->ChainCallback) 35 | { 36 | // Forward to user callback, if any 37 | data->UserData = user_data->ChainCallbackUserData; 38 | return user_data->ChainCallback(data); 39 | } 40 | return 0; 41 | } 42 | 43 | bool ImGui::InputText(const char* label, std::string* str, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data) 44 | { 45 | IM_ASSERT((flags & ImGuiInputTextFlags_CallbackResize) == 0); 46 | flags |= ImGuiInputTextFlags_CallbackResize; 47 | 48 | InputTextCallback_UserData cb_user_data; 49 | cb_user_data.Str = str; 50 | cb_user_data.ChainCallback = callback; 51 | cb_user_data.ChainCallbackUserData = user_data; 52 | return InputText(label, (char*)str->c_str(), str->capacity() + 1, flags, InputTextCallback, &cb_user_data); 53 | } 54 | 55 | bool ImGui::InputTextMultiline(const char* label, std::string* str, const ImVec2& size, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data) 56 | { 57 | IM_ASSERT((flags & ImGuiInputTextFlags_CallbackResize) == 0); 58 | flags |= ImGuiInputTextFlags_CallbackResize; 59 | 60 | InputTextCallback_UserData cb_user_data; 61 | cb_user_data.Str = str; 62 | cb_user_data.ChainCallback = callback; 63 | cb_user_data.ChainCallbackUserData = user_data; 64 | return InputTextMultiline(label, (char*)str->c_str(), str->capacity() + 1, size, flags, InputTextCallback, &cb_user_data); 65 | } 66 | 67 | bool ImGui::InputTextWithHint(const char* label, const char* hint, std::string* str, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data) 68 | { 69 | IM_ASSERT((flags & ImGuiInputTextFlags_CallbackResize) == 0); 70 | flags |= ImGuiInputTextFlags_CallbackResize; 71 | 72 | InputTextCallback_UserData cb_user_data; 73 | cb_user_data.Str = str; 74 | cb_user_data.ChainCallback = callback; 75 | cb_user_data.ChainCallbackUserData = user_data; 76 | return InputTextWithHint(label, hint, (char*)str->c_str(), str->capacity() + 1, flags, InputTextCallback, &cb_user_data); 77 | } 78 | -------------------------------------------------------------------------------- /TinyEngine/include/imgui/misc/cpp/imgui_stdlib.h: -------------------------------------------------------------------------------- 1 | // imgui_stdlib.h 2 | // Wrappers for C++ standard library (STL) types (std::string, etc.) 3 | // This is also an example of how you may wrap your own similar types. 4 | 5 | // Compatibility: 6 | // - std::string support is only guaranteed to work from C++11. 7 | // If you try to use it pre-C++11, please share your findings (w/ info about compiler/architecture) 8 | 9 | // Changelog: 10 | // - v0.10: Initial version. Added InputText() / InputTextMultiline() calls with std::string 11 | 12 | #pragma once 13 | 14 | #include 15 | 16 | namespace ImGui 17 | { 18 | // ImGui::InputText() with std::string 19 | // Because text input needs dynamic resizing, we need to setup a callback to grow the capacity 20 | IMGUI_API bool InputText(const char* label, std::string* str, ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = NULL, void* user_data = NULL); 21 | IMGUI_API bool InputTextMultiline(const char* label, std::string* str, const ImVec2& size = ImVec2(0, 0), ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = NULL, void* user_data = NULL); 22 | IMGUI_API bool InputTextWithHint(const char* label, const char* hint, std::string* str, ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = NULL, void* user_data = NULL); 23 | } 24 | -------------------------------------------------------------------------------- /TinyEngine/include/imgui/misc/fonts/Cousine-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weigert/MicroClimate/8fa73f2a43bd5b7537a0b113b1c441f6e08ea6bc/TinyEngine/include/imgui/misc/fonts/Cousine-Regular.ttf -------------------------------------------------------------------------------- /TinyEngine/include/imgui/misc/fonts/DroidSans.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weigert/MicroClimate/8fa73f2a43bd5b7537a0b113b1c441f6e08ea6bc/TinyEngine/include/imgui/misc/fonts/DroidSans.ttf -------------------------------------------------------------------------------- /TinyEngine/include/imgui/misc/fonts/Karla-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weigert/MicroClimate/8fa73f2a43bd5b7537a0b113b1c441f6e08ea6bc/TinyEngine/include/imgui/misc/fonts/Karla-Regular.ttf -------------------------------------------------------------------------------- /TinyEngine/include/imgui/misc/fonts/ProggyClean.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weigert/MicroClimate/8fa73f2a43bd5b7537a0b113b1c441f6e08ea6bc/TinyEngine/include/imgui/misc/fonts/ProggyClean.ttf -------------------------------------------------------------------------------- /TinyEngine/include/imgui/misc/fonts/ProggyTiny.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weigert/MicroClimate/8fa73f2a43bd5b7537a0b113b1c441f6e08ea6bc/TinyEngine/include/imgui/misc/fonts/ProggyTiny.ttf -------------------------------------------------------------------------------- /TinyEngine/include/imgui/misc/fonts/README.txt: -------------------------------------------------------------------------------- 1 | dear imgui, v1.73 WIP 2 | (Font Readme) 3 | 4 | --------------------------------------- 5 | 6 | The code in imgui.cpp embeds a copy of 'ProggyClean.ttf' (by Tristan Grimmer), 7 | a 13 pixels high, pixel-perfect font used by default. 8 | We embed it font in source code so you can use Dear ImGui without any file system access. 9 | 10 | You may also load external .TTF/.OTF files. 11 | The files in this folder are suggested fonts, provided as a convenience. 12 | 13 | Fonts are rasterized in a single texture at the time of calling either of io.Fonts->GetTexDataAsAlpha8()/GetTexDataAsRGBA32()/Build(). 14 | Also read dear imgui FAQ in imgui.cpp! 15 | 16 | If you have other loading/merging/adding fonts, you can post on the Dear ImGui "Getting Started" forum: 17 | https://discourse.dearimgui.org/c/getting-started 18 | 19 | 20 | --------------------------------------- 21 | INDEX: 22 | --------------------------------------- 23 | 24 | - Readme First / FAQ 25 | - Using Icons 26 | - Fonts Loading Instructions 27 | - FreeType rasterizer, Small font sizes 28 | - Building Custom Glyph Ranges 29 | - Using custom colorful icons 30 | - Embedding Fonts in Source Code 31 | - Credits/Licences for fonts included in this folder 32 | - Fonts Links 33 | 34 | 35 | --------------------------------------- 36 | README FIRST / FAQ 37 | --------------------------------------- 38 | 39 | - You can use the style editor ImGui::ShowStyleEditor() in the "Fonts" section to browse your fonts 40 | and understand what's going on if you have an issue. 41 | - Make sure your font ranges data are persistent (available during the call to GetTexDataAsAlpha8()/GetTexDataAsRGBA32()/Build(). 42 | - Use C++11 u8"my text" syntax to encode literal strings as UTF-8. e.g.: 43 | u8"hello" 44 | u8"こんにちは" // this will be encoded as UTF-8 45 | - If you want to include a backslash \ character in your string literal, you need to double them e.g. "folder\\filename". 46 | - Please use the Discourse forum (https://discourse.dearimgui.org) and not the Github issue tracker for basic font loading questions. 47 | 48 | 49 | --------------------------------------- 50 | USING ICONS 51 | --------------------------------------- 52 | 53 | Using an icon font (such as FontAwesome: http://fontawesome.io or OpenFontIcons. https://github.com/traverseda/OpenFontIcons) 54 | is an easy and practical way to use icons in your Dear ImGui application. 55 | A common pattern is to merge the icon font within your main font, so you can embed icons directly from your strings without 56 | having to change fonts back and forth. 57 | 58 | To refer to the icon UTF-8 codepoints from your C++ code, you may use those headers files created by Juliette Foucaut: 59 | https://github.com/juliettef/IconFontCppHeaders 60 | 61 | The C++11 version of those files uses the u8"" utf-8 encoding syntax + \u 62 | #define ICON_FA_SEARCH u8"\uf002" 63 | The pre-C++11 version has the values directly encoded as utf-8: 64 | #define ICON_FA_SEARCH "\xEF\x80\x82" 65 | 66 | Example Setup: 67 | 68 | // Merge icons into default tool font 69 | #include "IconsFontAwesome.h" 70 | ImGuiIO& io = ImGui::GetIO(); 71 | io.Fonts->AddFontDefault(); 72 | 73 | ImFontConfig config; 74 | config.MergeMode = true; 75 | config.GlyphMinAdvanceX = 13.0f; // Use if you want to make the icon monospaced 76 | static const ImWchar icon_ranges[] = { ICON_MIN_FA, ICON_MAX_FA, 0 }; 77 | io.Fonts->AddFontFromFileTTF("fonts/fontawesome-webfont.ttf", 13.0f, &config, icon_ranges); 78 | 79 | Example Usage: 80 | 81 | // Usage, e.g. 82 | ImGui::Text("%s among %d items", ICON_FA_SEARCH, count); 83 | ImGui::Button(ICON_FA_SEARCH " Search"); 84 | // C string _literals_ can be concatenated at compilation time, e.g. "hello" " world" 85 | // ICON_FA_SEARCH is defined as a string literal so this is the same as "A" "B" becoming "AB" 86 | 87 | See Links below for other icons fonts and related tools. 88 | 89 | 90 | --------------------------------------- 91 | FONTS LOADING INSTRUCTIONS 92 | --------------------------------------- 93 | 94 | Load default font: 95 | 96 | ImGuiIO& io = ImGui::GetIO(); 97 | io.Fonts->AddFontDefault(); 98 | 99 | Load .TTF/.OTF file with: 100 | 101 | ImGuiIO& io = ImGui::GetIO(); 102 | ImFont* font1 = io.Fonts->AddFontFromFileTTF("font.ttf", size_pixels); 103 | ImFont* font2 = io.Fonts->AddFontFromFileTTF("anotherfont.otf", size_pixels); 104 | 105 | // Select font at runtime 106 | ImGui::Text("Hello"); // use the default font (which is the first loaded font) 107 | ImGui::PushFont(font2); 108 | ImGui::Text("Hello with another font"); 109 | ImGui::PopFont(); 110 | 111 | For advanced options create a ImFontConfig structure and pass it to the AddFont function (it will be copied internally): 112 | 113 | ImFontConfig config; 114 | config.OversampleH = 2; 115 | config.OversampleV = 1; 116 | config.GlyphExtraSpacing.x = 1.0f; 117 | ImFont* font = io.Fonts->AddFontFromFileTTF("font.ttf", size_pixels, &config); 118 | 119 | Read about oversampling here: 120 | https://github.com/nothings/stb/blob/master/tests/oversample 121 | 122 | If you have very large number of glyphs or multiple fonts, the texture may become too big for your graphics API. 123 | The typical result of failing to upload a texture is if every glyphs appears as white rectangles. 124 | In particular, using a large range such as GetGlyphRangesChineseSimplifiedCommon() is not recommended unless you 125 | set OversampleH/OversampleV to 1 and use a small font size. 126 | Mind the fact that some graphics drivers have texture size limitation. 127 | If you are building a PC application, mind the fact that your users may use hardware with lower limitations than yours. 128 | Some solutions: 129 | 130 | - 1) Reduce glyphs ranges by calculating them from source localization data. 131 | You can use ImFontGlyphRangesBuilder for this purpose, this will be the biggest win! 132 | - 2) You may reduce oversampling, e.g. config.OversampleH = config.OversampleV = 1, this will largely reduce your texture size. 133 | - 3) Set io.Fonts.TexDesiredWidth to specify a texture width to minimize texture height (see comment in ImFontAtlas::Build function). 134 | - 4) Set io.Fonts.Flags |= ImFontAtlasFlags_NoPowerOfTwoHeight; to disable rounding the texture height to the next power of two. 135 | 136 | Combine two fonts into one: 137 | 138 | // Load a first font 139 | ImFont* font = io.Fonts->AddFontDefault(); 140 | 141 | // Add character ranges and merge into the previous font 142 | // The ranges array is not copied by the AddFont* functions and is used lazily 143 | // so ensure it is available at the time of building or calling GetTexDataAsRGBA32(). 144 | static const ImWchar icons_ranges[] = { 0xf000, 0xf3ff, 0 }; // Will not be copied by AddFont* so keep in scope. 145 | ImFontConfig config; 146 | config.MergeMode = true; 147 | io.Fonts->AddFontFromFileTTF("DroidSans.ttf", 18.0f, &config, io.Fonts->GetGlyphRangesJapanese()); 148 | io.Fonts->AddFontFromFileTTF("fontawesome-webfont.ttf", 18.0f, &config, icons_ranges); 149 | io.Fonts->Build(); 150 | 151 | Add a fourth parameter to bake specific font ranges only: 152 | 153 | // Basic Latin, Extended Latin 154 | io.Fonts->AddFontFromFileTTF("font.ttf", size_pixels, NULL, io.Fonts->GetGlyphRangesDefault()); 155 | 156 | // Default + Selection of 2500 Ideographs used by Simplified Chinese 157 | io.Fonts->AddFontFromFileTTF("font.ttf", size_pixels, NULL, io.Fonts->GetGlyphRangesChineseSimplifiedCommon()); 158 | 159 | // Default + Hiragana, Katakana, Half-Width, Selection of 1946 Ideographs 160 | io.Fonts->AddFontFromFileTTF("font.ttf", size_pixels, NULL, io.Fonts->GetGlyphRangesJapanese()); 161 | 162 | See "BUILDING CUSTOM GLYPH RANGES" section to create your own ranges. 163 | Offset font vertically by altering the io.Font->DisplayOffset value: 164 | 165 | ImFont* font = io.Fonts->AddFontFromFileTTF("font.ttf", size_pixels); 166 | font->DisplayOffset.y = 1; // Render 1 pixel down 167 | 168 | 169 | --------------------------------------- 170 | FREETYPE RASTERIZER, SMALL FONT SIZES 171 | --------------------------------------- 172 | 173 | Dear ImGui uses imstb_truetype.h to rasterize fonts (with optional oversampling). 174 | This technique and its implementation are not ideal for fonts rendered at _small sizes_, which may appear a 175 | little blurry or hard to read. 176 | 177 | There is an implementation of the ImFontAtlas builder using FreeType that you can use in the misc/freetype/ folder. 178 | 179 | FreeType supports auto-hinting which tends to improve the readability of small fonts. 180 | Note that this code currently creates textures that are unoptimally too large (could be fixed with some work). 181 | Also note that correct sRGB space blending will have an important effect on your font rendering quality. 182 | 183 | 184 | --------------------------------------- 185 | BUILDING CUSTOM GLYPH RANGES 186 | --------------------------------------- 187 | 188 | You can use the ImFontGlyphRangesBuilder helper to create glyph ranges based on text input. 189 | For example: for a game where your script is known, if you can feed your entire script to it and only build the characters the game needs. 190 | 191 | ImVector ranges; 192 | ImFontGlyphRangesBuilder builder; 193 | builder.AddText("Hello world"); // Add a string (here "Hello world" contains 7 unique characters) 194 | builder.AddChar(0x7262); // Add a specific character 195 | builder.AddRanges(io.Fonts->GetGlyphRangesJapanese()); // Add one of the default ranges 196 | builder.BuildRanges(&ranges); // Build the final result (ordered ranges with all the unique characters submitted) 197 | 198 | io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_in_pixels, NULL, ranges.Data); 199 | io.Fonts->Build(); // Build the atlas while 'ranges' is still in scope and not deleted. 200 | 201 | 202 | --------------------------------------- 203 | USING CUSTOM COLORFUL ICONS 204 | --------------------------------------- 205 | 206 | (This is a BETA api, use if you are familiar with dear imgui and with your rendering back-end) 207 | 208 | You can use the ImFontAtlas::AddCustomRect() and ImFontAtlas::AddCustomRectFontGlyph() api to register rectangles 209 | that will be packed into the font atlas texture. Register them before building the atlas, then call Build(). 210 | You can then use ImFontAtlas::GetCustomRectByIndex(int) to query the position/size of your rectangle within the 211 | texture, and blit/copy any graphics data of your choice into those rectangles. 212 | 213 | Pseudo-code: 214 | 215 | // Add font, then register two custom 13x13 rectangles mapped to glyph 'a' and 'b' of this font 216 | ImFont* font = io.Fonts->AddFontDefault(); 217 | int rect_ids[2]; 218 | rect_ids[0] = io.Fonts->AddCustomRectFontGlyph(font, 'a', 13, 13, 13+1); 219 | rect_ids[1] = io.Fonts->AddCustomRectFontGlyph(font, 'b', 13, 13, 13+1); 220 | 221 | // Build atlas 222 | io.Fonts->Build(); 223 | 224 | // Retrieve texture in RGBA format 225 | unsigned char* tex_pixels = NULL; 226 | int tex_width, tex_height; 227 | io.Fonts->GetTexDataAsRGBA32(&tex_pixels, &tex_width, &tex_height); 228 | 229 | for (int rect_n = 0; rect_n < IM_ARRAYSIZE(rect_ids); rect_n++) 230 | { 231 | int rect_id = rects_ids[rect_n]; 232 | if (const ImFontAtlas::CustomRect* rect = io.Fonts->GetCustomRectByIndex(rect_id)) 233 | { 234 | // Fill the custom rectangle with red pixels (in reality you would draw/copy your bitmap data here!) 235 | for (int y = 0; y < rect->Height; y++) 236 | { 237 | ImU32* p = (ImU32*)tex_pixels + (rect->Y + y) * tex_width + (rect->X); 238 | for (int x = rect->Width; x > 0; x--) 239 | *p++ = IM_COL32(255, 0, 0, 255); 240 | } 241 | } 242 | } 243 | 244 | 245 | --------------------------------------- 246 | EMBEDDING FONTS IN SOURCE CODE 247 | --------------------------------------- 248 | 249 | Compile and use 'binary_to_compressed_c.cpp' to create a compressed C style array that you can embed in source code. 250 | See the documentation in binary_to_compressed_c.cpp for instruction on how to use the tool. 251 | You may find a precompiled version binary_to_compressed_c.exe for Windows instead of demo binaries package (see README). 252 | The tool can optionally output Base85 encoding to reduce the size of _source code_ but the read-only arrays in the 253 | actual binary will be about 20% bigger. 254 | 255 | Then load the font with: 256 | ImFont* font = io.Fonts->AddFontFromMemoryCompressedTTF(compressed_data, compressed_data_size, size_pixels, ...); 257 | or: 258 | ImFont* font = io.Fonts->AddFontFromMemoryCompressedBase85TTF(compressed_data_base85, size_pixels, ...); 259 | 260 | 261 | --------------------------------------- 262 | CREDITS/LICENSES FOR FONTS INCLUDED IN THIS FOLDER 263 | --------------------------------------- 264 | 265 | Roboto-Medium.ttf 266 | 267 | Apache License 2.0 268 | by Christian Robertson 269 | https://fonts.google.com/specimen/Roboto 270 | 271 | Cousine-Regular.ttf 272 | 273 | by Steve Matteson 274 | Digitized data copyright (c) 2010 Google Corporation. 275 | Licensed under the SIL Open Font License, Version 1.1 276 | https://fonts.google.com/specimen/Cousine 277 | 278 | DroidSans.ttf 279 | 280 | Copyright (c) Steve Matteson 281 | Apache License, version 2.0 282 | https://www.fontsquirrel.com/fonts/droid-sans 283 | 284 | ProggyClean.ttf 285 | 286 | Copyright (c) 2004, 2005 Tristan Grimmer 287 | MIT License 288 | recommended loading setting: Size = 13.0, DisplayOffset.Y = +1 289 | http://www.proggyfonts.net/ 290 | 291 | ProggyTiny.ttf 292 | Copyright (c) 2004, 2005 Tristan Grimmer 293 | MIT License 294 | recommended loading setting: Size = 10.0, DisplayOffset.Y = +1 295 | http://www.proggyfonts.net/ 296 | 297 | Karla-Regular.ttf 298 | Copyright (c) 2012, Jonathan Pinhorn 299 | SIL OPEN FONT LICENSE Version 1.1 300 | 301 | 302 | --------------------------------------- 303 | FONTS LINKS 304 | --------------------------------------- 305 | 306 | ICON FONTS 307 | 308 | C/C++ header for icon fonts (#define with code points to use in source code string literals) 309 | https://github.com/juliettef/IconFontCppHeaders 310 | 311 | FontAwesome 312 | https://fortawesome.github.io/Font-Awesome 313 | 314 | OpenFontIcons 315 | https://github.com/traverseda/OpenFontIcons 316 | 317 | Google Icon Fonts 318 | https://design.google.com/icons/ 319 | 320 | Kenney Icon Font (Game Controller Icons) 321 | https://github.com/nicodinh/kenney-icon-font 322 | 323 | IcoMoon - Custom Icon font builder 324 | https://icomoon.io/app 325 | 326 | REGULAR FONTS 327 | 328 | Google Noto Fonts (worldwide languages) 329 | https://www.google.com/get/noto/ 330 | 331 | Open Sans Fonts 332 | https://fonts.google.com/specimen/Open+Sans 333 | 334 | (Japanese) M+ fonts by Coji Morishita are free 335 | http://mplus-fonts.sourceforge.jp/mplus-outline-fonts/index-en.html 336 | 337 | MONOSPACE FONTS 338 | 339 | (Pixel Perfect) Proggy Fonts, by Tristan Grimmer 340 | http://www.proggyfonts.net or http://upperbounds.net 341 | 342 | (Pixel Perfect) Sweet16, Sweet16 Mono, by Martin Sedlak (Latin + Supplemental + Extended A) 343 | https://github.com/kmar/Sweet16Font 344 | Also include .inl file to use directly in dear imgui. 345 | 346 | Google Noto Mono Fonts 347 | https://www.google.com/get/noto/ 348 | 349 | Typefaces for source code beautification 350 | https://github.com/chrissimpkins/codeface 351 | 352 | Programmation fonts 353 | http://s9w.github.io/font_compare/ 354 | 355 | Inconsolata 356 | http://www.levien.com/type/myfonts/inconsolata.html 357 | 358 | Adobe Source Code Pro: Monospaced font family for user interface and coding environments 359 | https://github.com/adobe-fonts/source-code-pro 360 | 361 | Monospace/Fixed Width Programmer's Fonts 362 | http://www.lowing.org/fonts/ 363 | 364 | 365 | Or use Arial Unicode or other Unicode fonts provided with Windows for full characters coverage (not sure of their licensing). 366 | -------------------------------------------------------------------------------- /TinyEngine/include/imgui/misc/fonts/Roboto-Medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weigert/MicroClimate/8fa73f2a43bd5b7537a0b113b1c441f6e08ea6bc/TinyEngine/include/imgui/misc/fonts/Roboto-Medium.ttf -------------------------------------------------------------------------------- /TinyEngine/include/imgui/misc/fonts/binary_to_compressed_c.cpp: -------------------------------------------------------------------------------- 1 | // ImGui - binary_to_compressed_c.cpp 2 | // Helper tool to turn a file into a C array, if you want to embed font data in your source code. 3 | 4 | // The data is first compressed with stb_compress() to reduce source code size, 5 | // then encoded in Base85 to fit in a string so we can fit roughly 4 bytes of compressed data into 5 bytes of source code (suggested by @mmalex) 6 | // (If we used 32-bits constants it would require take 11 bytes of source code to encode 4 bytes, and be endianness dependent) 7 | // Note that even with compression, the output array is likely to be bigger than the binary file.. 8 | // Load compressed TTF fonts with ImGui::GetIO().Fonts->AddFontFromMemoryCompressedTTF() 9 | 10 | // Build with, e.g: 11 | // # cl.exe binary_to_compressed_c.cpp 12 | // # gcc binary_to_compressed_c.cpp 13 | // You can also find a precompiled Windows binary in the binary/demo package available from https://github.com/ocornut/imgui 14 | 15 | // Usage: 16 | // binary_to_compressed_c.exe [-base85] [-nocompress] 17 | // Usage example: 18 | // # binary_to_compressed_c.exe myfont.ttf MyFont > myfont.cpp 19 | // # binary_to_compressed_c.exe -base85 myfont.ttf MyFont > myfont.cpp 20 | 21 | #define _CRT_SECURE_NO_WARNINGS 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | // stb_compress* from stb.h - declaration 28 | typedef unsigned int stb_uint; 29 | typedef unsigned char stb_uchar; 30 | stb_uint stb_compress(stb_uchar *out,stb_uchar *in,stb_uint len); 31 | 32 | static bool binary_to_compressed_c(const char* filename, const char* symbol, bool use_base85_encoding, bool use_compression); 33 | 34 | int main(int argc, char** argv) 35 | { 36 | if (argc < 3) 37 | { 38 | printf("Syntax: %s [-base85] [-nocompress] \n", argv[0]); 39 | return 0; 40 | } 41 | 42 | int argn = 1; 43 | bool use_base85_encoding = false; 44 | bool use_compression = true; 45 | if (argv[argn][0] == '-') 46 | { 47 | if (strcmp(argv[argn], "-base85") == 0) { use_base85_encoding = true; argn++; } 48 | else if (strcmp(argv[argn], "-nocompress") == 0) { use_compression = false; argn++; } 49 | else 50 | { 51 | fprintf(stderr, "Unknown argument: '%s'\n", argv[argn]); 52 | return 1; 53 | } 54 | } 55 | 56 | bool ret = binary_to_compressed_c(argv[argn], argv[argn+1], use_base85_encoding, use_compression); 57 | if (!ret) 58 | fprintf(stderr, "Error opening or reading file: '%s'\n", argv[argn]); 59 | return ret ? 0 : 1; 60 | } 61 | 62 | char Encode85Byte(unsigned int x) 63 | { 64 | x = (x % 85) + 35; 65 | return (x>='\\') ? x+1 : x; 66 | } 67 | 68 | bool binary_to_compressed_c(const char* filename, const char* symbol, bool use_base85_encoding, bool use_compression) 69 | { 70 | // Read file 71 | FILE* f = fopen(filename, "rb"); 72 | if (!f) return false; 73 | int data_sz; 74 | if (fseek(f, 0, SEEK_END) || (data_sz = (int)ftell(f)) == -1 || fseek(f, 0, SEEK_SET)) { fclose(f); return false; } 75 | char* data = new char[data_sz+4]; 76 | if (fread(data, 1, data_sz, f) != (size_t)data_sz) { fclose(f); delete[] data; return false; } 77 | memset((void*)(((char*)data) + data_sz), 0, 4); 78 | fclose(f); 79 | 80 | // Compress 81 | int maxlen = data_sz + 512 + (data_sz >> 2) + sizeof(int); // total guess 82 | char* compressed = use_compression ? new char[maxlen] : data; 83 | int compressed_sz = use_compression ? stb_compress((stb_uchar*)compressed, (stb_uchar*)data, data_sz) : data_sz; 84 | if (use_compression) 85 | memset(compressed + compressed_sz, 0, maxlen - compressed_sz); 86 | 87 | // Output as Base85 encoded 88 | FILE* out = stdout; 89 | fprintf(out, "// File: '%s' (%d bytes)\n", filename, (int)data_sz); 90 | fprintf(out, "// Exported using binary_to_compressed_c.cpp\n"); 91 | const char* compressed_str = use_compression ? "compressed_" : ""; 92 | if (use_base85_encoding) 93 | { 94 | fprintf(out, "static const char %s_%sdata_base85[%d+1] =\n \"", symbol, compressed_str, (int)((compressed_sz+3)/4)*5); 95 | char prev_c = 0; 96 | for (int src_i = 0; src_i < compressed_sz; src_i += 4) 97 | { 98 | // This is made a little more complicated by the fact that ??X sequences are interpreted as trigraphs by old C/C++ compilers. So we need to escape pairs of ??. 99 | unsigned int d = *(unsigned int*)(compressed + src_i); 100 | for (unsigned int n5 = 0; n5 < 5; n5++, d /= 85) 101 | { 102 | char c = Encode85Byte(d); 103 | fprintf(out, (c == '?' && prev_c == '?') ? "\\%c" : "%c", c); 104 | prev_c = c; 105 | } 106 | if ((src_i % 112) == 112-4) 107 | fprintf(out, "\"\n \""); 108 | } 109 | fprintf(out, "\";\n\n"); 110 | } 111 | else 112 | { 113 | fprintf(out, "static const unsigned int %s_%ssize = %d;\n", symbol, compressed_str, (int)compressed_sz); 114 | fprintf(out, "static const unsigned int %s_%sdata[%d/4] =\n{", symbol, compressed_str, (int)((compressed_sz+3)/4)*4); 115 | int column = 0; 116 | for (int i = 0; i < compressed_sz; i += 4) 117 | { 118 | unsigned int d = *(unsigned int*)(compressed + i); 119 | if ((column++ % 12) == 0) 120 | fprintf(out, "\n 0x%08x, ", d); 121 | else 122 | fprintf(out, "0x%08x, ", d); 123 | } 124 | fprintf(out, "\n};\n\n"); 125 | } 126 | 127 | // Cleanup 128 | delete[] data; 129 | if (use_compression) 130 | delete[] compressed; 131 | return true; 132 | } 133 | 134 | // stb_compress* from stb.h - definition 135 | 136 | //////////////////// compressor /////////////////////// 137 | 138 | static stb_uint stb_adler32(stb_uint adler32, stb_uchar *buffer, stb_uint buflen) 139 | { 140 | const unsigned long ADLER_MOD = 65521; 141 | unsigned long s1 = adler32 & 0xffff, s2 = adler32 >> 16; 142 | unsigned long blocklen, i; 143 | 144 | blocklen = buflen % 5552; 145 | while (buflen) { 146 | for (i=0; i + 7 < blocklen; i += 8) { 147 | s1 += buffer[0], s2 += s1; 148 | s1 += buffer[1], s2 += s1; 149 | s1 += buffer[2], s2 += s1; 150 | s1 += buffer[3], s2 += s1; 151 | s1 += buffer[4], s2 += s1; 152 | s1 += buffer[5], s2 += s1; 153 | s1 += buffer[6], s2 += s1; 154 | s1 += buffer[7], s2 += s1; 155 | 156 | buffer += 8; 157 | } 158 | 159 | for (; i < blocklen; ++i) 160 | s1 += *buffer++, s2 += s1; 161 | 162 | s1 %= ADLER_MOD, s2 %= ADLER_MOD; 163 | buflen -= blocklen; 164 | blocklen = 5552; 165 | } 166 | return (s2 << 16) + s1; 167 | } 168 | 169 | static unsigned int stb_matchlen(stb_uchar *m1, stb_uchar *m2, stb_uint maxlen) 170 | { 171 | stb_uint i; 172 | for (i=0; i < maxlen; ++i) 173 | if (m1[i] != m2[i]) return i; 174 | return i; 175 | } 176 | 177 | // simple implementation that just takes the source data in a big block 178 | 179 | static stb_uchar *stb__out; 180 | static FILE *stb__outfile; 181 | static stb_uint stb__outbytes; 182 | 183 | static void stb__write(unsigned char v) 184 | { 185 | fputc(v, stb__outfile); 186 | ++stb__outbytes; 187 | } 188 | 189 | //#define stb_out(v) (stb__out ? *stb__out++ = (stb_uchar) (v) : stb__write((stb_uchar) (v))) 190 | #define stb_out(v) do { if (stb__out) *stb__out++ = (stb_uchar) (v); else stb__write((stb_uchar) (v)); } while (0) 191 | 192 | static void stb_out2(stb_uint v) { stb_out(v >> 8); stb_out(v); } 193 | static void stb_out3(stb_uint v) { stb_out(v >> 16); stb_out(v >> 8); stb_out(v); } 194 | static void stb_out4(stb_uint v) { stb_out(v >> 24); stb_out(v >> 16); stb_out(v >> 8 ); stb_out(v); } 195 | 196 | static void outliterals(stb_uchar *in, int numlit) 197 | { 198 | while (numlit > 65536) { 199 | outliterals(in,65536); 200 | in += 65536; 201 | numlit -= 65536; 202 | } 203 | 204 | if (numlit == 0) ; 205 | else if (numlit <= 32) stb_out (0x000020 + numlit-1); 206 | else if (numlit <= 2048) stb_out2(0x000800 + numlit-1); 207 | else /* numlit <= 65536) */ stb_out3(0x070000 + numlit-1); 208 | 209 | if (stb__out) { 210 | memcpy(stb__out,in,numlit); 211 | stb__out += numlit; 212 | } else 213 | fwrite(in, 1, numlit, stb__outfile); 214 | } 215 | 216 | static int stb__window = 0x40000; // 256K 217 | 218 | static int stb_not_crap(int best, int dist) 219 | { 220 | return ((best > 2 && dist <= 0x00100) 221 | || (best > 5 && dist <= 0x04000) 222 | || (best > 7 && dist <= 0x80000)); 223 | } 224 | 225 | static stb_uint stb__hashsize = 32768; 226 | 227 | // note that you can play with the hashing functions all you 228 | // want without needing to change the decompressor 229 | #define stb__hc(q,h,c) (((h) << 7) + ((h) >> 25) + q[c]) 230 | #define stb__hc2(q,h,c,d) (((h) << 14) + ((h) >> 18) + (q[c] << 7) + q[d]) 231 | #define stb__hc3(q,c,d,e) ((q[c] << 14) + (q[d] << 7) + q[e]) 232 | 233 | static unsigned int stb__running_adler; 234 | 235 | static int stb_compress_chunk(stb_uchar *history, 236 | stb_uchar *start, 237 | stb_uchar *end, 238 | int length, 239 | int *pending_literals, 240 | stb_uchar **chash, 241 | stb_uint mask) 242 | { 243 | (void)history; 244 | int window = stb__window; 245 | stb_uint match_max; 246 | stb_uchar *lit_start = start - *pending_literals; 247 | stb_uchar *q = start; 248 | 249 | #define STB__SCRAMBLE(h) (((h) + ((h) >> 16)) & mask) 250 | 251 | // stop short of the end so we don't scan off the end doing 252 | // the hashing; this means we won't compress the last few bytes 253 | // unless they were part of something longer 254 | while (q < start+length && q+12 < end) { 255 | int m; 256 | stb_uint h1,h2,h3,h4, h; 257 | stb_uchar *t; 258 | int best = 2, dist=0; 259 | 260 | if (q+65536 > end) 261 | match_max = end-q; 262 | else 263 | match_max = 65536; 264 | 265 | #define stb__nc(b,d) ((d) <= window && ((b) > 9 || stb_not_crap(b,d))) 266 | 267 | #define STB__TRY(t,p) /* avoid retrying a match we already tried */ \ 268 | if (p ? dist != q-t : 1) \ 269 | if ((m = stb_matchlen(t, q, match_max)) > best) \ 270 | if (stb__nc(m,q-(t))) \ 271 | best = m, dist = q - (t) 272 | 273 | // rather than search for all matches, only try 4 candidate locations, 274 | // chosen based on 4 different hash functions of different lengths. 275 | // this strategy is inspired by LZO; hashing is unrolled here using the 276 | // 'hc' macro 277 | h = stb__hc3(q,0, 1, 2); h1 = STB__SCRAMBLE(h); 278 | t = chash[h1]; if (t) STB__TRY(t,0); 279 | h = stb__hc2(q,h, 3, 4); h2 = STB__SCRAMBLE(h); 280 | h = stb__hc2(q,h, 5, 6); t = chash[h2]; if (t) STB__TRY(t,1); 281 | h = stb__hc2(q,h, 7, 8); h3 = STB__SCRAMBLE(h); 282 | h = stb__hc2(q,h, 9,10); t = chash[h3]; if (t) STB__TRY(t,1); 283 | h = stb__hc2(q,h,11,12); h4 = STB__SCRAMBLE(h); 284 | t = chash[h4]; if (t) STB__TRY(t,1); 285 | 286 | // because we use a shared hash table, can only update it 287 | // _after_ we've probed all of them 288 | chash[h1] = chash[h2] = chash[h3] = chash[h4] = q; 289 | 290 | if (best > 2) 291 | assert(dist > 0); 292 | 293 | // see if our best match qualifies 294 | if (best < 3) { // fast path literals 295 | ++q; 296 | } else if (best > 2 && best <= 0x80 && dist <= 0x100) { 297 | outliterals(lit_start, q-lit_start); lit_start = (q += best); 298 | stb_out(0x80 + best-1); 299 | stb_out(dist-1); 300 | } else if (best > 5 && best <= 0x100 && dist <= 0x4000) { 301 | outliterals(lit_start, q-lit_start); lit_start = (q += best); 302 | stb_out2(0x4000 + dist-1); 303 | stb_out(best-1); 304 | } else if (best > 7 && best <= 0x100 && dist <= 0x80000) { 305 | outliterals(lit_start, q-lit_start); lit_start = (q += best); 306 | stb_out3(0x180000 + dist-1); 307 | stb_out(best-1); 308 | } else if (best > 8 && best <= 0x10000 && dist <= 0x80000) { 309 | outliterals(lit_start, q-lit_start); lit_start = (q += best); 310 | stb_out3(0x100000 + dist-1); 311 | stb_out2(best-1); 312 | } else if (best > 9 && dist <= 0x1000000) { 313 | if (best > 65536) best = 65536; 314 | outliterals(lit_start, q-lit_start); lit_start = (q += best); 315 | if (best <= 0x100) { 316 | stb_out(0x06); 317 | stb_out3(dist-1); 318 | stb_out(best-1); 319 | } else { 320 | stb_out(0x04); 321 | stb_out3(dist-1); 322 | stb_out2(best-1); 323 | } 324 | } else { // fallback literals if no match was a balanced tradeoff 325 | ++q; 326 | } 327 | } 328 | 329 | // if we didn't get all the way, add the rest to literals 330 | if (q-start < length) 331 | q = start+length; 332 | 333 | // the literals are everything from lit_start to q 334 | *pending_literals = (q - lit_start); 335 | 336 | stb__running_adler = stb_adler32(stb__running_adler, start, q - start); 337 | return q - start; 338 | } 339 | 340 | static int stb_compress_inner(stb_uchar *input, stb_uint length) 341 | { 342 | int literals = 0; 343 | stb_uint len,i; 344 | 345 | stb_uchar **chash; 346 | chash = (stb_uchar**) malloc(stb__hashsize * sizeof(stb_uchar*)); 347 | if (chash == NULL) return 0; // failure 348 | for (i=0; i < stb__hashsize; ++i) 349 | chash[i] = NULL; 350 | 351 | // stream signature 352 | stb_out(0x57); stb_out(0xbc); 353 | stb_out2(0); 354 | 355 | stb_out4(0); // 64-bit length requires 32-bit leading 0 356 | stb_out4(length); 357 | stb_out4(stb__window); 358 | 359 | stb__running_adler = 1; 360 | 361 | len = stb_compress_chunk(input, input, input+length, length, &literals, chash, stb__hashsize-1); 362 | assert(len == length); 363 | 364 | outliterals(input+length - literals, literals); 365 | 366 | free(chash); 367 | 368 | stb_out2(0x05fa); // end opcode 369 | 370 | stb_out4(stb__running_adler); 371 | 372 | return 1; // success 373 | } 374 | 375 | stb_uint stb_compress(stb_uchar *out, stb_uchar *input, stb_uint length) 376 | { 377 | stb__out = out; 378 | stb__outfile = NULL; 379 | 380 | stb_compress_inner(input, length); 381 | 382 | return stb__out - out; 383 | } 384 | -------------------------------------------------------------------------------- /TinyEngine/include/imgui/misc/freetype/README.md: -------------------------------------------------------------------------------- 1 | # imgui_freetype 2 | 3 | Build font atlases using FreeType instead of stb_truetype (which is the default font rasterizer in Dear ImGui). 4 |
by @vuhdo, @mikesart, @ocornut. 5 | 6 | ### Usage 7 | 8 | 1. Get latest FreeType binaries or build yourself (under Windows you may use vcpkg with `vcpkg install freetype`). 9 | 2. Add imgui_freetype.h/cpp alongside your imgui sources. 10 | 3. Include imgui_freetype.h after imgui.h. 11 | 4. Call `ImGuiFreeType::BuildFontAtlas()` *BEFORE* calling `ImFontAtlas::GetTexDataAsRGBA32()` or `ImFontAtlas::Build()` (so normal Build() won't be called): 12 | 13 | ```cpp 14 | // See ImGuiFreeType::RasterizationFlags 15 | unsigned int flags = ImGuiFreeType::NoHinting; 16 | ImGuiFreeType::BuildFontAtlas(io.Fonts, flags); 17 | io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); 18 | ``` 19 | 20 | ### Gamma Correct Blending 21 | 22 | FreeType assumes blending in linear space rather than gamma space. 23 | See FreeType note for [FT_Render_Glyph](https://www.freetype.org/freetype2/docs/reference/ft2-base_interface.html#FT_Render_Glyph). 24 | For correct results you need to be using sRGB and convert to linear space in the pixel shader output. 25 | The default Dear ImGui styles will be impacted by this change (alpha values will need tweaking). 26 | 27 | ### Test code Usage 28 | ```cpp 29 | #include "misc/freetype/imgui_freetype.h" 30 | #include "misc/freetype/imgui_freetype.cpp" 31 | 32 | // Load various small fonts 33 | ImGuiIO& io = ImGui::GetIO(); 34 | io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 13.0f); 35 | io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 13.0f); 36 | io.Fonts->AddFontDefault(); 37 | 38 | FreeTypeTest freetype_test; 39 | 40 | // Main Loop 41 | while (true) 42 | { 43 | if (freetype_test.UpdateRebuild()) 44 | { 45 | // REUPLOAD FONT TEXTURE TO GPU 46 | ImGui_ImplXXX_DestroyDeviceObjects(); 47 | ImGui_ImplXXX_CreateDeviceObjects(); 48 | } 49 | ImGui::NewFrame(); 50 | freetype_test.ShowFreetypeOptionsWindow(); 51 | ... 52 | } 53 | ``` 54 | 55 | ### Test code 56 | ```cpp 57 | #include "misc/freetype/imgui_freetype.h" 58 | #include "misc/freetype/imgui_freetype.cpp" 59 | 60 | struct FreeTypeTest 61 | { 62 | enum FontBuildMode 63 | { 64 | FontBuildMode_FreeType, 65 | FontBuildMode_Stb 66 | }; 67 | 68 | FontBuildMode BuildMode; 69 | bool WantRebuild; 70 | float FontsMultiply; 71 | int FontsPadding; 72 | unsigned int FontsFlags; 73 | 74 | FreeTypeTest() 75 | { 76 | BuildMode = FontBuildMode_FreeType; 77 | WantRebuild = true; 78 | FontsMultiply = 1.0f; 79 | FontsPadding = 1; 80 | FontsFlags = 0; 81 | } 82 | 83 | // Call _BEFORE_ NewFrame() 84 | bool UpdateRebuild() 85 | { 86 | if (!WantRebuild) 87 | return false; 88 | ImGuiIO& io = ImGui::GetIO(); 89 | io.Fonts->TexGlyphPadding = FontsPadding; 90 | for (int n = 0; n < io.Fonts->ConfigData.Size; n++) 91 | { 92 | ImFontConfig* font_config = (ImFontConfig*)&io.Fonts->ConfigData[n]; 93 | font_config->RasterizerMultiply = FontsMultiply; 94 | font_config->RasterizerFlags = (BuildMode == FontBuildMode_FreeType) ? FontsFlags : 0x00; 95 | } 96 | if (BuildMode == FontBuildMode_FreeType) 97 | ImGuiFreeType::BuildFontAtlas(io.Fonts, FontsFlags); 98 | else if (BuildMode == FontBuildMode_Stb) 99 | io.Fonts->Build(); 100 | WantRebuild = false; 101 | return true; 102 | } 103 | 104 | // Call to draw interface 105 | void ShowFreetypeOptionsWindow() 106 | { 107 | ImGui::Begin("FreeType Options"); 108 | ImGui::ShowFontSelector("Fonts"); 109 | WantRebuild |= ImGui::RadioButton("FreeType", (int*)&BuildMode, FontBuildMode_FreeType); 110 | ImGui::SameLine(); 111 | WantRebuild |= ImGui::RadioButton("Stb (Default)", (int*)&BuildMode, FontBuildMode_Stb); 112 | WantRebuild |= ImGui::DragFloat("Multiply", &FontsMultiply, 0.001f, 0.0f, 2.0f); 113 | WantRebuild |= ImGui::DragInt("Padding", &FontsPadding, 0.1f, 0, 16); 114 | if (BuildMode == FontBuildMode_FreeType) 115 | { 116 | WantRebuild |= ImGui::CheckboxFlags("NoHinting", &FontsFlags, ImGuiFreeType::NoHinting); 117 | WantRebuild |= ImGui::CheckboxFlags("NoAutoHint", &FontsFlags, ImGuiFreeType::NoAutoHint); 118 | WantRebuild |= ImGui::CheckboxFlags("ForceAutoHint", &FontsFlags, ImGuiFreeType::ForceAutoHint); 119 | WantRebuild |= ImGui::CheckboxFlags("LightHinting", &FontsFlags, ImGuiFreeType::LightHinting); 120 | WantRebuild |= ImGui::CheckboxFlags("MonoHinting", &FontsFlags, ImGuiFreeType::MonoHinting); 121 | WantRebuild |= ImGui::CheckboxFlags("Bold", &FontsFlags, ImGuiFreeType::Bold); 122 | WantRebuild |= ImGui::CheckboxFlags("Oblique", &FontsFlags, ImGuiFreeType::Oblique); 123 | WantRebuild |= ImGui::CheckboxFlags("Monochrome", &FontsFlags, ImGuiFreeType::Monochrome); 124 | } 125 | ImGui::End(); 126 | } 127 | }; 128 | ``` 129 | 130 | ### Known issues 131 | - `cfg.OversampleH`, `OversampleV` are ignored (but perhaps not so necessary with this rasterizer). 132 | 133 | -------------------------------------------------------------------------------- /TinyEngine/include/imgui/misc/freetype/imgui_freetype.h: -------------------------------------------------------------------------------- 1 | // Wrapper to use FreeType (instead of stb_truetype) for Dear ImGui 2 | // Get latest version at https://github.com/ocornut/imgui/tree/master/misc/freetype 3 | // Original code by @Vuhdo (Aleksei Skriabin), maintained by @ocornut 4 | 5 | #pragma once 6 | 7 | #include "imgui.h" // IMGUI_API, ImFontAtlas 8 | 9 | namespace ImGuiFreeType 10 | { 11 | // Hinting greatly impacts visuals (and glyph sizes). 12 | // When disabled, FreeType generates blurrier glyphs, more or less matches the stb's output. 13 | // The Default hinting mode usually looks good, but may distort glyphs in an unusual way. 14 | // The Light hinting mode generates fuzzier glyphs but better matches Microsoft's rasterizer. 15 | 16 | // You can set those flags on a per font basis in ImFontConfig::RasterizerFlags. 17 | // Use the 'extra_flags' parameter of BuildFontAtlas() to force a flag on all your fonts. 18 | enum RasterizerFlags 19 | { 20 | // By default, hinting is enabled and the font's native hinter is preferred over the auto-hinter. 21 | NoHinting = 1 << 0, // Disable hinting. This generally generates 'blurrier' bitmap glyphs when the glyph are rendered in any of the anti-aliased modes. 22 | NoAutoHint = 1 << 1, // Disable auto-hinter. 23 | ForceAutoHint = 1 << 2, // Indicates that the auto-hinter is preferred over the font's native hinter. 24 | LightHinting = 1 << 3, // A lighter hinting algorithm for gray-level modes. Many generated glyphs are fuzzier but better resemble their original shape. This is achieved by snapping glyphs to the pixel grid only vertically (Y-axis), as is done by Microsoft's ClearType and Adobe's proprietary font renderer. This preserves inter-glyph spacing in horizontal text. 25 | MonoHinting = 1 << 4, // Strong hinting algorithm that should only be used for monochrome output. 26 | Bold = 1 << 5, // Styling: Should we artificially embolden the font? 27 | Oblique = 1 << 6, // Styling: Should we slant the font, emulating italic style? 28 | Monochrome = 1 << 7 // Disable anti-aliasing. Combine this with MonoHinting for best results! 29 | }; 30 | 31 | IMGUI_API bool BuildFontAtlas(ImFontAtlas* atlas, unsigned int extra_flags = 0); 32 | 33 | // By default ImGuiFreeType will use IM_ALLOC()/IM_FREE(). 34 | // However, as FreeType does lots of allocations we provide a way for the user to redirect it to a separate memory heap if desired: 35 | IMGUI_API void SetAllocatorFunctions(void* (*alloc_func)(size_t sz, void* user_data), void (*free_func)(void* ptr, void* user_data), void* user_data = NULL); 36 | } 37 | -------------------------------------------------------------------------------- /TinyEngine/include/imgui/misc/natvis/README.txt: -------------------------------------------------------------------------------- 1 | 2 | Natvis file to describe dear imgui types in the Visual Studio debugger. 3 | With this, types like ImVector<> will be displayed nicely in the debugger. 4 | You can include this file a Visual Studio project file, or install it in Visual Studio folder. 5 | -------------------------------------------------------------------------------- /TinyEngine/include/imgui/misc/natvis/imgui.natvis: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | {{Size={Size} Capacity={Capacity}}} 9 | 10 | 11 | Size 12 | Data 13 | 14 | 15 | 16 | 17 | 18 | {{x={x,g} y={y,g}}} 19 | 20 | 21 | 22 | {{x={x,g} y={y,g} z={z,g} w={w,g}}} 23 | 24 | 25 | 26 | {{Min=({Min.x,g} {Min.y,g}) Max=({Max.x,g} {Max.y,g}) Size=({Max.x-Min.x,g} {Max.y-Min.y,g})}} 27 | 28 | Min 29 | Max 30 | Max.x - Min.x 31 | Max.y - Min.y 32 | 33 | 34 | 35 | 36 | {{Name {Name,s} Active {(Active||WasActive)?1:0,d} Child {(Flags & 0x01000000)?1:0,d} Popup {(Flags & 0x04000000)?1:0,d} Hidden {(Hidden)?1:0,d}} 37 | 38 | 39 | -------------------------------------------------------------------------------- /TinyEngine/include/utility/instance.cpp: -------------------------------------------------------------------------------- 1 | class Instance{ 2 | public: 3 | 4 | Instance(Primitive* _m){ 5 | m = _m; 6 | }; 7 | 8 | ~Instance(){ 9 | for(auto& b: instances){ 10 | glDeleteBuffers(1, &b); 11 | } 12 | } 13 | 14 | Primitive* m; //Instanced Render Model (must be derived from primitive) 15 | std::vector instances; //Instance VBO Pointers 16 | unsigned int SIZE; //Number of Instances 17 | 18 | template void addBuffer(std::vector& buf); 19 | template void updateBuffer(std::vector& buf, int index); 20 | template void configBuffer(GLuint instance); 21 | 22 | void render(GLenum mode = GL_TRIANGLE_STRIP); //Default because of primitive models 23 | }; 24 | 25 | template 26 | void Instance::addBuffer(std::vector& buf){ 27 | GLuint instance; 28 | glGenBuffers(1, &instance); 29 | SIZE = buf.size(); //Update the Number of Instances 30 | 31 | glBindVertexArray(m->vao); 32 | glBindBuffer(GL_ARRAY_BUFFER, instance); //Bind Instance Buffer and Data 33 | glBufferData(GL_ARRAY_BUFFER, SIZE*sizeof(D), &buf[0], GL_STATIC_DRAW); 34 | 35 | configBuffer(instance); 36 | } 37 | 38 | template 39 | void Instance::configBuffer(GLuint instance){ 40 | glEnableVertexAttribArray(m->vbo.size()+instances.size()); 41 | glVertexAttribPointer(m->vbo.size()+instances.size(), sizeof(D)/sizeof(GLfloat), GL_FLOAT, GL_FALSE, 0, (void*)0); 42 | glVertexAttribDivisor(m->vbo.size()+instances.size(), 1); 43 | instances.push_back(instance); 44 | } 45 | 46 | template<> //For Matrices - Special Procedure 47 | void Instance::configBuffer(GLuint instance){ 48 | for(int i = 0; i < 4; i++){ 49 | glEnableVertexAttribArray(m->vbo.size()+instances.size()); 50 | glVertexAttribPointer(m->vbo.size()+instances.size(), 4, GL_FLOAT, GL_FALSE, 4*sizeof(glm::vec4), (void*)(i*sizeof(glm::vec4))); 51 | glVertexAttribDivisor(m->vbo.size()+instances.size(), 1); 52 | instances.push_back(instance); 53 | } 54 | } 55 | 56 | template 57 | void Instance::updateBuffer(std::vector& buf, int index){ 58 | glBindVertexArray(m->vao); 59 | glBindBuffer(GL_ARRAY_BUFFER, instances[index]); //Bind Instance Buffer and Data 60 | if(buf.size() != SIZE) glBufferData(GL_ARRAY_BUFFER, buf.size()*sizeof(D), &buf[0], GL_STATIC_DRAW); 61 | else glBufferSubData(GL_ARRAY_BUFFER, 0, SIZE*sizeof(D), &buf[0]); 62 | SIZE = buf.size(); 63 | } 64 | 65 | void Instance::render(GLenum mode){ 66 | glBindVertexArray(m->vao); 67 | glDrawArraysInstanced(mode, 0, m->SIZE, SIZE); //Instanced render 68 | } 69 | -------------------------------------------------------------------------------- /TinyEngine/include/utility/model.cpp: -------------------------------------------------------------------------------- 1 | struct Primitive{ 2 | 3 | Primitive(){ 4 | glGenVertexArrays(1, &vao); 5 | glBindVertexArray(vao); 6 | addBuffers(2); 7 | } 8 | 9 | ~Primitive(){ 10 | glDisableVertexAttribArray(vao); 11 | clearBuffers(); 12 | glDeleteVertexArrays(1, &vao); 13 | } 14 | 15 | void addBuffers(int n){ 16 | GLuint nvbo; 17 | for(int i = 0; i < n; i++){ 18 | glGenBuffers(1, &nvbo); 19 | vbo.push_back(nvbo); 20 | } 21 | } 22 | 23 | void clearBuffers(){ 24 | while(!vbo.empty()){ 25 | glDeleteBuffers(1, &(vbo.back())); 26 | vbo.pop_back(); 27 | } 28 | } 29 | 30 | GLuint vao; 31 | std::vector vbo; 32 | size_t SIZE = 4; 33 | 34 | template 35 | void bind(int index, int count, int size, T* data){ 36 | glBindBuffer(GL_ARRAY_BUFFER, vbo[index]); 37 | glBufferData(GL_ARRAY_BUFFER, count*sizeof(T), data, GL_DYNAMIC_DRAW); 38 | attrib(index, size); 39 | } 40 | 41 | template 42 | void attrib(int index, int size){ 43 | std::cout<<"Data type not recognized."< 69 | void Primitive::attrib(int index, int size){ 70 | glEnableVertexAttribArray(index); 71 | glVertexAttribPointer(index, size, GL_FLOAT, GL_FALSE, 0, 0); 72 | } 73 | 74 | //Primitive Shapes (Pre-Made) 75 | 76 | struct Square2D: Primitive{ 77 | GLfloat vert[8] = {-1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0, -1.0}; 78 | GLfloat tex [8] = { 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0}; 79 | 80 | Square2D():Primitive(){ 81 | bind(0, 8, 2, &vert[0]); 82 | bind(1, 8, 2, &tex[0]); 83 | } 84 | }; 85 | 86 | struct Square3D: Primitive{ 87 | GLfloat vert[12] = {-1.0, 1.0, 0.0, -1.0, -1.0, 0.0, 1.0, 1.0, 0.0, 1.0, -1.0, 0.0}; 88 | GLfloat tex [8] = { 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0}; 89 | 90 | Square3D():Primitive(){ 91 | bind(0, 12, 3, &vert[0]); 92 | bind(1, 8, 2, &tex[0]); 93 | } 94 | }; 95 | 96 | class Model: public Primitive { 97 | public: 98 | Model():Primitive(){ 99 | glGenBuffers(1, &ibo); //Additional Index Buffer 100 | addBuffers(1); //Additional Color Buffer 101 | } 102 | 103 | Model(std::function c):Model(){ 104 | construct(c); 105 | } 106 | 107 | template //Pass Parameters to Model Constructing Function 108 | Model(std::function c, T... t):Model(){ 109 | construct(c, t...); 110 | } 111 | 112 | ~Model(){ 113 | glDisableVertexAttribArray(vao); 114 | clearBuffers(); 115 | glDeleteBuffers(1, &ibo); 116 | glDeleteVertexArrays(1, &vao); 117 | } 118 | 119 | std::vector positions, normals, colors; 120 | std::vector indices; 121 | 122 | bool indexed = true; 123 | GLuint ibo; 124 | 125 | void update(){ 126 | glBindVertexArray(vao); 127 | bind(0, positions.size(), 3, &positions[0]); 128 | if(!normals.empty()) bind(1, normals.size(), 3, &normals[0]); 129 | if(!colors.empty()) bind(2, colors.size(), 4, &colors[0]); 130 | 131 | SIZE = indices.size(); 132 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo); 133 | glBufferData(GL_ELEMENT_ARRAY_BUFFER, SIZE*sizeof(GLuint), &indices[0], GL_DYNAMIC_DRAW); 134 | } 135 | 136 | void construct(std::function constructor){ 137 | positions.clear(); 138 | normals.clear(); 139 | colors.clear(); 140 | indices.clear(); 141 | 142 | (constructor)(this); //Call user-defined constructor 143 | update(); //Update VAO / VBO / IBO 144 | } 145 | 146 | template 147 | void construct(std::function constructor, T... t){ 148 | positions.clear(); 149 | normals.clear(); 150 | colors.clear(); 151 | indices.clear(); 152 | 153 | (constructor)(this, t...); //Call user-defined constructor 154 | update(); //Update VAO / VBO / IBO 155 | } 156 | 157 | void render(GLenum mode = GL_TRIANGLES){ 158 | glBindVertexArray(vao); 159 | if(indexed){ 160 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo); 161 | glDrawElements(mode, SIZE, GL_UNSIGNED_INT, 0); 162 | } 163 | else glDrawArrays(mode, 0, positions.size()/3); 164 | } 165 | }; 166 | -------------------------------------------------------------------------------- /TinyEngine/include/utility/shader.cpp: -------------------------------------------------------------------------------- 1 | class Shader{ 2 | public: 3 | template 4 | Shader(slist shaders, slist in){ 5 | program = glCreateProgram(); //Generate Shader 6 | setup(shaders); //Add Individual Shaders 7 | for(auto &n : in) //Add all Attributes of Shader 8 | glBindAttribLocation(program, &n - in.begin(), n.c_str()); 9 | link(); //Link the shader program! 10 | } 11 | 12 | Shader(slist shaders, slist in){ 13 | program = glCreateProgram(); //Generate Shader 14 | setup(shaders); //Add Individual Shaders 15 | for(auto &n : in) //Add all Attributes of Shader 16 | glBindAttribLocation(program, &n - in.begin(), n.c_str()); 17 | link(); //Link the shader program! 18 | } 19 | 20 | Shader(slist shaders, slist in, slist buf):Shader(shaders, in){ 21 | for(auto&b : buf) addBuffer(b); //Add Storage Buffers to Shader 22 | } 23 | 24 | ~Shader(){ 25 | glDeleteProgram(program); 26 | glDeleteShader(fragmentShader); 27 | glDeleteShader(geometryShader); 28 | glDeleteShader(vertexShader); 29 | } 30 | 31 | GLuint program; //Shader Program ID 32 | GLuint vertexShader, geometryShader, fragmentShader; 33 | int boundtextures; 34 | 35 | std::unordered_map ssbo; //SSBO Storage 36 | std::unordered_map sbpi; //Shader Binding Point Index 37 | 38 | void setup(slist shaders); 39 | int addProgram(std::string fileName, GLenum shaderType); //General Shader Addition 40 | std::string readGLSLFile(std::string fileName, int32_t &size); //Read File 41 | void compile(GLuint shader); //Compile and Add File 42 | void link(); //Link the entire program 43 | void error(GLuint s, bool t); //Get Compile/Link Error 44 | void use(); //Use the program 45 | void addBuffer(std::string name); //General Buffer Addition 46 | 47 | template void texture(std::string name, const T& t); 48 | template void buffer(std::string name, std::vector& buf, bool update = false); 49 | template void uniform(std::string name, const T u); 50 | template void uniform(std::string name, const T (&u)[N]); 51 | }; 52 | 53 | void Shader::setup(slist _s){ 54 | boost::filesystem::path data_dir(boost::filesystem::current_path()); 55 | std::vector s = _s; 56 | 57 | if(s.size() == 2){ 58 | vertexShader = addProgram((data_dir/s[0]).string(), GL_VERTEX_SHADER); 59 | fragmentShader = addProgram((data_dir/s[1]).string(), GL_FRAGMENT_SHADER); 60 | } 61 | else if(s.size() == 3){ 62 | vertexShader = addProgram((data_dir/s[0]).string(), GL_VERTEX_SHADER); 63 | geometryShader = addProgram((data_dir/s[1]).string(), GL_GEOMETRY_SHADER); 64 | fragmentShader = addProgram((data_dir/s[2]).string(), GL_FRAGMENT_SHADER); 65 | } 66 | else std::cout<<"Number of shaders not recognized."<(result.c_str()); 73 | 74 | int shaderID = glCreateShader(shaderType); 75 | glShaderSource(shaderID, 1, &src, &size); 76 | compile(shaderID); 77 | 78 | return shaderID; 79 | } 80 | 81 | void Shader::compile(GLuint shader){ 82 | glCompileShader(shader); 83 | int success; 84 | glGetShaderiv(shader, GL_COMPILE_STATUS, &success); 85 | if(success) glAttachShader(program, shader); 86 | else error(shader, true); 87 | } 88 | 89 | void Shader::link(){ 90 | glLinkProgram(program); 91 | int success; 92 | glGetProgramiv(program, GL_LINK_STATUS, &success); 93 | if(!success) error(program, false); 94 | } 95 | 96 | void Shader::error(GLuint s, bool t){ 97 | int m; 98 | if(t) glGetShaderiv(s, GL_INFO_LOG_LENGTH, &m); 99 | else glGetProgramiv(s, GL_INFO_LOG_LENGTH, &m); 100 | char* l = new char[m]; 101 | if(t) glGetShaderInfoLog(s, m, &m, l); 102 | else glGetProgramInfoLog(s, m, &m, l); 103 | std::cout<<"Linker Error: "< 143 | void Shader::buffer(std::string name, std::vector& buf, bool update){ 144 | glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo[name]); 145 | if(update) glBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, buf.size()*sizeof(T), &buf[0]); 146 | else glBufferData(GL_SHADER_STORAGE_BUFFER, buf.size()*sizeof(T), &buf[0], GL_STATIC_DRAW); 147 | glBindBufferBase(GL_SHADER_STORAGE_BUFFER, sbpi[name], ssbo[name]); 148 | glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); 149 | } 150 | 151 | /* Uniform Setters */ 152 | 153 | template 154 | void Shader::uniform(std::string name, T u){ 155 | std::cout<<"Error: Data type not recognized for uniform "< 158 | void Shader::uniform(std::string name, const T (&u)[N]){ 159 | std::cout<<"Error: Data type not recognized for uniform "< void Shader::uniform(std::string name, const bool u){ 162 | glUniform1i(glGetUniformLocation(program, name.c_str()), u); } 163 | 164 | template<> void Shader::uniform(std::string name, const int u){ 165 | glUniform1i(glGetUniformLocation(program, name.c_str()), u); } 166 | 167 | template<> void Shader::uniform(std::string name, const float u){ 168 | glUniform1f(glGetUniformLocation(program, name.c_str()), u); } 169 | 170 | template<> void Shader::uniform(std::string name, const double u){ //GLSL Intrinsically Single Precision 171 | glUniform1f(glGetUniformLocation(program, name.c_str()), (float)u); } 172 | 173 | template<> void Shader::uniform(std::string name, const glm::vec2 u){ 174 | glUniform2fv(glGetUniformLocation(program, name.c_str()), 1, &u[0]); } 175 | 176 | template<> void Shader::uniform(std::string name, const glm::vec3 u){ 177 | glUniform3fv(glGetUniformLocation(program, name.c_str()), 1, &u[0]); } 178 | 179 | template<> void Shader::uniform(std::string name, const float (&u)[3]){ 180 | glUniform3fv(glGetUniformLocation(program, name.c_str()), 1, &u[0]); } 181 | 182 | template<> void Shader::uniform(std::string name, const float (&u)[4]){ 183 | glUniform4fv(glGetUniformLocation(program, name.c_str()), 1, &u[0]); } 184 | 185 | template<> void Shader::uniform(std::string name, const glm::vec4 u){ 186 | glUniform4fv(glGetUniformLocation(program, name.c_str()), 1, &u[0]); } 187 | 188 | template<> void Shader::uniform(std::string name, const glm::mat3 u){ 189 | glUniformMatrix3fv(glGetUniformLocation(program, name.c_str()), 1, GL_FALSE, &u[0][0]); } 190 | 191 | template<> void Shader::uniform(std::string name, const glm::mat4 u){ 192 | glUniformMatrix4fv(glGetUniformLocation(program, name.c_str()), 1, GL_FALSE, &u[0][0]); } 193 | 194 | template<> void Shader::uniform(std::string name, const std::vector u){ 195 | glUniformMatrix4fv(glGetUniformLocation(program, name.c_str()), u.size(), GL_FALSE, &u[0][0][0]); } 196 | 197 | template 198 | void Shader::texture(std::string name, const T& t){ 199 | glActiveTexture(GL_TEXTURE0 + boundtextures); 200 | glBindTexture(t.type, t.texture); 201 | uniform(name, boundtextures++); 202 | } 203 | -------------------------------------------------------------------------------- /TinyEngine/include/utility/target.cpp: -------------------------------------------------------------------------------- 1 | class Target { 2 | public: 3 | Target(){ glGenFramebuffers(1, &fbo); }; //Default constructor 4 | 5 | Target(int W, int H, bool c = false, bool d = true): //Construct with a size 6 | Target(){ WIDTH = W; HEIGHT = H; dAttach = d; cAttach = c; } 7 | 8 | ~Target(){ glDeleteFramebuffers(1, &fbo); } //Default destructor 9 | 10 | unsigned int WIDTH, HEIGHT; 11 | bool dAttach = false, cAttach = true; //Whether we have a depth / color attachment 12 | GLuint fbo; //FBO (OpenGL: everything is an int) 13 | 14 | template 15 | void bind(T& t, bool d){ //Bind a texture to the FBO 16 | if(d) glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, t.texture, 0); 17 | else glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, t.texture, 0); 18 | } 19 | 20 | template 21 | void setup(T& t, T& d){ //Add color and depth textures! 22 | glBindFramebuffer(GL_FRAMEBUFFER, fbo); 23 | 24 | if(dAttach) bind(d, true); 25 | if(cAttach) bind(t, false); 26 | else{ //If we don't have a color attachment, don't draw to it 27 | glDrawBuffer(GL_NONE); 28 | glReadBuffer(GL_NONE); 29 | } 30 | 31 | if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) 32 | std::cout<<"Framebuffer Incomplete"< void target(T a){ 44 | glClearColor(a[0], a[1], a[2], 1.0f); 45 | target(); 46 | } 47 | }; 48 | 49 | class Billboard: public Target{ //Billboard specialization 50 | public: 51 | Texture texture, depth; //Two normal textures 52 | 53 | Billboard(int W, int H, bool c = true, bool d = true): 54 | Target(W, H, c, d){ 55 | if(dAttach) depth.depth(WIDTH, HEIGHT); 56 | if(cAttach) texture.empty(WIDTH, HEIGHT); 57 | setup(texture, depth); //Bind the two normal textures to the billboard 58 | } 59 | 60 | Billboard(SDL_Surface* s): //Render target preloaded with an image 61 | Billboard(s->w, s->h, true, false){ 62 | texture.raw(s); //Construct the texture from raw surface data 63 | bind(texture, false); //Bind it to the billboard as color texture 64 | } 65 | }; 66 | 67 | class Cubemap: public Target{ //Cubemap specialization 68 | public: 69 | Cubetexture texture, depth; //Two cubemap textures 70 | 71 | Cubemap(int W, int H, bool c = true, bool d = true):Target(W, H, c, d){ 72 | if(dAttach) depth.depth(WIDTH, HEIGHT); 73 | if(cAttach) texture.empty(WIDTH, HEIGHT); 74 | setup(texture, depth); 75 | } 76 | }; 77 | -------------------------------------------------------------------------------- /TinyEngine/include/utility/texture.cpp: -------------------------------------------------------------------------------- 1 | class Texture; 2 | using tfunc = std::function; //Arbitrary function operating on texture pointer 3 | 4 | class Texture{ 5 | public: 6 | Texture(){ glGenTextures( 1, &texture ); }; //Default constructor 7 | Texture(SDL_Surface* s):Texture(){ raw(s); }; //Load raw surface data into texture 8 | Texture(int W, int H, bool d = false):Texture(){ //Create empty texture of defined size 9 | if(!d) empty(W, H); 10 | else depth(W, H); 11 | }; 12 | 13 | ~Texture(){ glDeleteTextures(1, &texture); } 14 | 15 | static tfunc parameter; //Texture Parameter Setter! 16 | GLuint texture; //Texture int (OpenGL: everything is an int!) 17 | GLenum type = GL_TEXTURE_2D; //Texture type (default is this) 18 | 19 | void empty(int W, int H, tfunc param = parameter, GLenum F = GL_RGBA){ 20 | glBindTexture( type, texture ); 21 | glTexImage2D(type, 0, F, W, H, 0, F, GL_UNSIGNED_BYTE, NULL); 22 | (param)(this); //Call Parameter Setter 23 | } 24 | 25 | void depth(int W, int H, tfunc param = parameter){ 26 | empty(W, H, param, GL_DEPTH_COMPONENT); 27 | } 28 | 29 | void raw(SDL_Surface* s, tfunc param = parameter){ //Generate a texture from raw surface data 30 | glBindTexture( type, texture ); 31 | glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); 32 | glTexImage2D(type, 0, GL_RGBA, s->w, s->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, s->pixels); 33 | (param)(this); //Call the parameter setting function! 34 | } 35 | }; 36 | 37 | //Default parameter setting function! 38 | //Note that you can pass your own to the texture building functions above!z 39 | tfunc Texture::parameter = [](Texture* t){ 40 | glTexParameteri(t->type, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 41 | glTexParameteri(t->type, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 42 | glTexParameteri(t->type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 43 | glTexParameteri(t->type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 44 | glTexParameteri(t->type, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); 45 | }; 46 | 47 | class Cubetexture: public Texture{ //Cubetexture specialization. 48 | public: //Same thing, 6 times 49 | Cubetexture():Texture(){ 50 | type = GL_TEXTURE_CUBE_MAP; 51 | }; 52 | 53 | Cubetexture(int W, int H, bool d = false):Cubetexture(){ //Create empty texture of defined size 54 | if(!d) empty(W, H); 55 | else depth(W, H); 56 | }; 57 | 58 | void empty(int W, int H, tfunc param = parameter, GLenum F = GL_RGBA){ 59 | glBindTexture(type, texture); 60 | for(unsigned int i = 0; i < 6; i++) 61 | glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, F, W, H, 0, F, GL_UNSIGNED_BYTE, NULL); 62 | (param)(this); 63 | } 64 | 65 | void depth(int W, int H, tfunc param = parameter){ 66 | empty(W, H, param, GL_DEPTH_COMPONENT); 67 | }; 68 | }; 69 | -------------------------------------------------------------------------------- /TinyEngine/include/view.cpp: -------------------------------------------------------------------------------- 1 | class View{ 2 | public: 3 | bool init(std::string windowName, int width, int height); 4 | void quit(); 5 | bool enabled = false; 6 | 7 | unsigned int WIDTH, HEIGHT; 8 | 9 | SDL_Window* gWindow; //Window Pointer 10 | SDL_GLContext gContext; //Render Context 11 | 12 | ImGuiIO io; 13 | Handle interface = [](){}; //User defined Interface 14 | bool showInterface = false; 15 | void drawInterface(); 16 | 17 | Handle pipeline = [](){}; //User defined Pipeline 18 | void render(); 19 | void target(glm::vec3 clearcolor); //Target main window for drawing 20 | 21 | bool fullscreen = false; //Settings 22 | bool vsync = true; 23 | bool ccw = true; 24 | unsigned int antialias = 16; 25 | float lineWidth = 1.0f; 26 | }; 27 | 28 | bool View::init(std::string _name, int W, int H){ 29 | enabled = true; 30 | WIDTH = W; HEIGHT = H; 31 | 32 | //Core OpenGL Profile! 33 | SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); 34 | 35 | if(antialias) 36 | SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, antialias); 37 | 38 | //Initialize the Window and Context 39 | gWindow = SDL_CreateWindow(_name.c_str(), SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, WIDTH, HEIGHT, SDL_WINDOW_OPENGL); 40 | if( gWindow == NULL ){ 41 | printf( "Window could not be created! SDL_Error: %s\n", SDL_GetError() ); 42 | return false; 43 | } 44 | SDL_SetWindowResizable(gWindow, SDL_TRUE); 45 | gContext = SDL_GL_CreateContext(gWindow); 46 | 47 | SDL_GL_SetSwapInterval(vsync); 48 | glewExperimental = GL_TRUE; //Launch GLEW 49 | glewInit(); 50 | 51 | IMGUI_CHECKVERSION(); //Setup ImGUI 52 | ImGui::CreateContext(); 53 | io = ImGui::GetIO(); (void)io; 54 | ImGui_ImplSDL2_InitForOpenGL(gWindow, gContext); 55 | ImGui_ImplOpenGL3_Init("#version 330 core"); 56 | ImGui::StyleColorsCustom(); 57 | 58 | if(antialias) 59 | glEnable(GL_MULTISAMPLE); 60 | glEnable(GL_DEPTH_TEST); //Setup Global OpenGL State! 61 | glDepthFunc(GL_LEQUAL); 62 | glEnable(GL_BLEND) ; 63 | glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 64 | glEnable(GL_CULL_FACE); 65 | if(ccw) glFrontFace(GL_CCW); 66 | else glFrontFace(GL_CW); 67 | glLineWidth(lineWidth); 68 | glBindFramebuffer(GL_FRAMEBUFFER, 0); 69 | 70 | return true; 71 | } 72 | 73 | void View::quit(){ 74 | ImGui_ImplOpenGL3_Shutdown(); //Shutdown ImGUI 75 | ImGui_ImplSDL2_Shutdown(); 76 | ImGui::DestroyContext(); 77 | 78 | SDL_GL_DeleteContext( gContext ); 79 | SDL_DestroyWindow( gWindow ); 80 | } 81 | 82 | void View::render(){ 83 | (pipeline)(); //User-Defined Pipeline call 84 | 85 | if(showInterface) //Draw the interface on top 86 | drawInterface(); 87 | 88 | SDL_GL_SwapWindow(gWindow); //Update Window 89 | } 90 | 91 | void View::drawInterface(){ 92 | ImGui_ImplOpenGL3_NewFrame(); 93 | ImGui_ImplSDL2_NewFrame(gWindow); 94 | ImGui::NewFrame(); 95 | 96 | (interface)(); //Draw user-defined interface 97 | //ImGui::ShowDemoWindow(); //Demo-Window (if you want) 98 | 99 | ImGui::Render(); 100 | glViewport(0, 0, (int)io.DisplaySize.x, (int)io.DisplaySize.y); 101 | ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); 102 | } 103 | 104 | void View::target(glm::vec3 clearcolor){ 105 | glBindFramebuffer(GL_FRAMEBUFFER, 0); 106 | glViewport(0, 0, WIDTH, HEIGHT); 107 | glClearColor(clearcolor.x, clearcolor.y, clearcolor.z, 1.0f); 108 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 109 | } 110 | -------------------------------------------------------------------------------- /TinyFluid/TinyFluid.h: -------------------------------------------------------------------------------- 1 | /* 2 | TinyFluid - Small Differential Equation Solver 3 | Author: Nicholas McDonald 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | 13 | // Core Stuff 14 | #include 15 | 16 | #include "include/src/algebra.h" //Space Discretizations 17 | #include "include/src/shape.h" //Shape Functions 18 | 19 | #include "include/src/space.h" //Space Discretizations 20 | #include "include/src/time.h" //Time Discretizations and Integrators 21 | #include "include/src/solve.h" //Full Scheme Solvers / Algorithms 22 | 23 | #include "include/helpers/timer.h" //Benchmarking Tool 24 | 25 | //#include "render/view.cpp" 26 | //#include "render/input.cpp" 27 | -------------------------------------------------------------------------------- /TinyFluid/include/helpers/timer.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | /* 7 | Author: Nicholas McDonald 8 | 9 | Timer Helper Namespace 10 | 11 | Can spawn a thread to execute something repeatedly, or benchmark your code. 12 | 13 | */ 14 | 15 | namespace timer{ 16 | 17 | //Benchmarking Helper 18 | template 19 | void benchmark(F function, Args&&... args){ 20 | auto start = std::chrono::high_resolution_clock::now(); 21 | function(args...); 22 | auto stop = std::chrono::high_resolution_clock::now(); 23 | auto duration = std::chrono::duration_cast(stop - start); 24 | std::cout<<"Execution Time: "<([&](){ 32 | //Your Code Here 33 | }); 34 | 35 | */ 36 | 37 | //Timed Execution Helper 38 | template 39 | class Timer{ 40 | //Finish the Guy 41 | std::atomic active = false; 42 | 43 | //Should keep track of execution time... 44 | std::chrono::time_point curTime; 45 | D delayTime = D(0); 46 | 47 | //Thread for the guy 48 | std::thread t; 49 | 50 | public: 51 | //Timeout Setter 52 | template 53 | void set_timeout(D duration, F function){ 54 | active = true; 55 | t = std::thread([=](){ 56 | std::this_thread::sleep_for(duration); 57 | if(!active) return; //Maybe the Thread was terminated before the execution of function 58 | function(); 59 | return; 60 | }); 61 | t.detach(); 62 | }; 63 | 64 | //Interval Setter 65 | template 66 | void set_interval(D* duration, F function, Args&&... args){ 67 | active = true; 68 | t = std::thread([=](){ 69 | while(active){ 70 | std::this_thread::sleep_for(*duration); 71 | function(args...); 72 | } 73 | return; 74 | }); 75 | t.detach(); 76 | }; 77 | 78 | //Interval Setter 79 | template 80 | void set_const_interval(D* duration, F function, Args&&... args){ 81 | active = true; 82 | t = std::thread([=](){ 83 | while(active){ 84 | std::this_thread::sleep_for(*duration-delayTime); 85 | curTime = std::chrono::high_resolution_clock::now(); 86 | function(args...); 87 | delayTime = std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - curTime); 88 | } 89 | return; 90 | }); 91 | t.detach(); 92 | }; 93 | 94 | //Stopper 95 | void stop(){ 96 | //Stop the Process and Join the Thread 97 | active = false; 98 | if(t.joinable()){ 99 | t.join(); 100 | } 101 | } 102 | }; 103 | } 104 | -------------------------------------------------------------------------------- /TinyFluid/include/render/color.h: -------------------------------------------------------------------------------- 1 | /* 2 | Author: Nicholas McDonald 3 | 4 | Bezier-Curve based Coloring Schemes and Interpolator! 5 | 6 | Stolen from my Territory Project 7 | 8 | */ 9 | 10 | namespace color{ 11 | 12 | typedef std::vector scheme; 13 | 14 | scheme bw{ 15 | glm::vec3(0.0, 0.0, 0.0), 16 | glm::vec3(1.0, 1.0, 1.0) 17 | }; 18 | 19 | glm::vec3 red = glm::vec3(1.0, 0.0, 0.0); 20 | glm::vec3 white = glm::vec3(1.0); 21 | glm::vec3 black = glm::vec3(0.0); 22 | 23 | scheme green{ 24 | glm::vec3(0.0, 1.0, 0.0) 25 | }; 26 | 27 | scheme ocean{ 28 | glm::vec3(0.18, 0.28, 0.35), 29 | glm::vec3(0.15, 0.41, 0.49), 30 | glm::vec3(0.00, 0.54, 0.60), 31 | glm::vec3(0.00, 0.68, 0.68), 32 | glm::vec3(0.07, 0.82, 0.71), 33 | glm::vec3(0.37, 0.96, 0.75) 34 | }; 35 | 36 | scheme land{ 37 | glm::vec3(0.18, 0.52, 0.34), 38 | glm::vec3(0.53, 0.69, 0.29), 39 | glm::vec3(0.75, 0.62, 0.23) 40 | }; 41 | 42 | 43 | scheme nebula{ 44 | glm::vec3(0.26, 0.33, 0.51), 45 | glm::vec3(0.50, 0.34, 0.59), 46 | glm::vec3(0.77, 0.30, 0.55), 47 | glm::vec3(0.96, 0.31, 0.38), 48 | glm::vec3(1.00, 0.46, 0.09) 49 | }; 50 | 51 | scheme ivory{ 52 | glm::vec3(0.18, 0.28, 0.35), 53 | glm::vec3(0.35, 0.40, 0.47), 54 | glm::vec3(0.52, 0.51, 0.59), 55 | glm::vec3(0.69, 0.64, 0.70), 56 | glm::vec3(0.85, 0.78, 0.82), 57 | glm::vec3(1.00, 0.93, 0.94) 58 | }; 59 | 60 | //Multiply Color by Constant Factor 61 | glm::vec3 operator*(const double &d, const glm::vec3& vec) { 62 | return glm::vec3(d)*vec; 63 | } 64 | 65 | //De-Casteljau Algorithm 66 | glm::vec3 bezier(double t, scheme col){ //t between 0 and 1 67 | //Recursively do Linear Interpolations 68 | while(col.size() > 1){ 69 | scheme next; 70 | for(unsigned int i = 0; i < col.size()-1; i++) 71 | next.push_back( (1.0-t)*col[i] + t*col[i+1] ); 72 | col = next; 73 | } 74 | return col[0]; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /TinyFluid/include/render/input.cpp: -------------------------------------------------------------------------------- 1 | #include "input.h" 2 | 3 | void Input::handle(){ 4 | //Do something with the input here! 5 | if( event.type == SDL_QUIT ) { quit = true; } 6 | else if( event.type == SDL_KEYDOWN ) { 7 | if(event.key.keysym.sym == SDLK_p){ 8 | paused = !paused; 9 | } 10 | else if(event.key.keysym.sym == SDLK_t){ 11 | trigger = true; 12 | } 13 | else if(event.key.keysym.sym == SDLK_SPACE){ 14 | screen = (screen+1)%6; 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /TinyFluid/include/render/input.h: -------------------------------------------------------------------------------- 1 | class Input{ 2 | public: 3 | bool quit = false; 4 | bool paused = true; 5 | bool trigger = false; 6 | int screen = 0; 7 | 8 | void handle(); 9 | SDL_Event event; 10 | }; 11 | -------------------------------------------------------------------------------- /TinyFluid/include/render/view.cpp: -------------------------------------------------------------------------------- 1 | #include "view.h" 2 | 3 | /* 4 | ================================================================================ 5 | SETUP / CLEANUP 6 | ================================================================================ 7 | */ 8 | 9 | bool View::setup(){ 10 | //Initialize SDL 11 | if( SDL_Init( SDL_INIT_VIDEO ) < 0 ) return false; 12 | 13 | //Create window 14 | gWindow = SDL_CreateWindow( WINDOW_NAME.c_str(), SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN ); 15 | if( gWindow == NULL ) return false; 16 | 17 | //Prepare the Renderer 18 | gRenderer = SDL_CreateRenderer(gWindow, -1, SDL_RENDERER_ACCELERATED); 19 | SDL_SetRenderDrawBlendMode(gRenderer, SDL_BLENDMODE_BLEND); 20 | SDL_GL_SetSwapInterval(false); 21 | 22 | return true; 23 | } 24 | 25 | void View::cleanup(){ 26 | //Destroy window 27 | SDL_DestroyWindow( gWindow ); 28 | SDL_DestroyRenderer (gRenderer); 29 | 30 | //Quit SDL subsystems 31 | SDL_Quit(); 32 | } 33 | 34 | /* 35 | ================================================================================ 36 | RENDER MASTER 37 | ================================================================================ 38 | */ 39 | 40 | template 41 | void View::render(F function, Args&&... args){ 42 | //Clear the Window 43 | // std::cout<<"Render "; 44 | // timer::benchmark([&](){ 45 | 46 | SDL_SetRenderDrawColor(gRenderer, 0, 0, 0, 255); 47 | SDL_RenderClear(gRenderer); 48 | 49 | //Call whatever the user has specified... 50 | function(args...); 51 | 52 | //Present the Information 53 | SDL_RenderPresent(gRenderer); 54 | 55 | // }); 56 | } 57 | 58 | /* 59 | ================================================================================ 60 | DRAWING HELPERS 61 | ================================================================================ 62 | */ 63 | 64 | void View::drawPixel(glm::ivec2 pos, glm::vec3 color, double opacity){ 65 | /* Construct a Rect and Fill with Color at Position */ 66 | int ratiox = SCREEN_WIDTH / SIZE; 67 | int ratioy = SCREEN_HEIGHT / SIZE; 68 | SDL_Rect rect{ratiox*pos.x, ratioy*pos.y, ratiox, ratioy}; 69 | SDL_SetRenderDrawColor(gRenderer, 255*color.x, 255*color.y, 255*color.z, 255*opacity); 70 | SDL_RenderFillRect(gRenderer, &rect); 71 | } 72 | 73 | void View::drawPixel(glm::ivec2 pos, glm::vec3 color, double opacity, int _SIZE){ 74 | /* Construct a Rect and Fill with Color at Position */ 75 | int ratiox = SCREEN_WIDTH / _SIZE; 76 | int ratioy = SCREEN_HEIGHT / _SIZE; 77 | SDL_Rect rect{ratiox*pos.x, ratioy*pos.y, ratiox, ratioy}; 78 | SDL_SetRenderDrawColor(gRenderer, 255*color.x, 255*color.y, 255*color.z, 255*opacity); 79 | SDL_RenderFillRect(gRenderer, &rect); 80 | } 81 | 82 | 83 | void View::drawLine(glm::vec2 pos, glm::vec2 dir){ 84 | double scale = 2.0; 85 | int ratiox = SCREEN_WIDTH / SIZE; 86 | int ratioy = SCREEN_HEIGHT / SIZE; 87 | 88 | /* I need Direction AND Intensity */ 89 | SDL_SetRenderDrawColor(gRenderer, 255, 255, 255, 255); 90 | SDL_RenderDrawLine(gRenderer, ratiox*(pos.x+0.5-scale*0.5*dir.x), ratioy*(pos.y+0.5-scale*0.5*dir.y), ratiox*(pos.x+0.5+scale*0.5*dir.x), ratioy*(pos.y+0.5+scale*0.5*dir.y)); 91 | } 92 | -------------------------------------------------------------------------------- /TinyFluid/include/render/view.h: -------------------------------------------------------------------------------- 1 | #define SCREEN_WIDTH 1000 2 | #define SCREEN_HEIGHT 1000 3 | 4 | #include 5 | #include 6 | #include "color.h" 7 | 8 | /* 9 | Author: Nicholas McDonald 10 | 11 | Simple SDL Wrapper that acts like a canvas which you can draw stuff onto. 12 | 13 | Drawing Helpers let you define the drawing behavior. 14 | 15 | The render wrapper lets you plug in a lambda of drawing helpers for rendering. 16 | */ 17 | 18 | 19 | //Master Class 20 | class View { 21 | public: 22 | std::string WINDOW_NAME = "Climate Simulator"; 23 | 24 | //Rendering Variables 25 | SDL_Window* gWindow; 26 | SDL_Renderer* gRenderer; 27 | 28 | //Setup and Cleanup 29 | bool setup(); 30 | void cleanup(); 31 | 32 | //Drawing Helpers 33 | void drawPixel(glm::ivec2 pos, glm::vec3 color, double opacity); 34 | void drawPixel(glm::ivec2 pos, glm::vec3 color, double opacity, int _SIZE); 35 | void drawLine(glm::vec2 pos, glm::vec2 dir); 36 | 37 | //Renderer 38 | template 39 | void render(F function, Args&&... args); 40 | }; 41 | -------------------------------------------------------------------------------- /TinyFluid/include/src/algebra.h: -------------------------------------------------------------------------------- 1 | //Useful Math Extensions 2 | typedef Eigen::Triplet triplet; 3 | 4 | namespace alg{ 5 | using namespace Eigen; 6 | 7 | //Convert Index to Coordinates and Back 8 | glm::ivec2 pos(int i){ 9 | return glm::ivec2(i/SIZE, i%SIZE); 10 | } 11 | 12 | int index(glm::vec2 pos){ 13 | return pos.x*SIZE + pos.y; 14 | } 15 | 16 | int index(int x, int y){ 17 | return x*SIZE + y; 18 | } 19 | 20 | Eigen::SparseMatrix sparseIdentity(){ 21 | Eigen::SparseMatrix I(SIZE*SIZE, SIZE*SIZE); 22 | I.setIdentity(); 23 | return I; 24 | } 25 | 26 | Eigen::SparseMatrix sparseDiagonalize(Eigen::VectorXd &vec){ 27 | Eigen::SparseMatrix I(SIZE*SIZE, SIZE*SIZE); 28 | std::vector list; 29 | for(int i = 0; i < SIZE*SIZE; i++){ 30 | list.push_back(triplet(i, i, vec(i))); 31 | } 32 | I.setFromTriplets(list.begin(), list.end()); 33 | return I; 34 | } 35 | 36 | void sparseDiagonalize(Eigen::VectorXd& vec, Eigen::SparseMatrix& vmat){ 37 | std::vector list; 38 | for(int i = 0; i < SIZE*SIZE; i++){ 39 | list.push_back(triplet(i, i, vec(i))); 40 | } 41 | vmat.setFromTriplets(list.begin(), list.end()); 42 | } 43 | 44 | //End of Namespace 45 | } 46 | 47 | glm::vec2 operator%(const glm::vec2& rhs, const int x){ 48 | return glm::mod(rhs, glm::vec2(x)); 49 | } 50 | 51 | glm::ivec2 operator%(const glm::ivec2& rhs, const int x){ 52 | return glm::mod(glm::vec2(rhs.x, rhs.y), glm::vec2(x)); 53 | } 54 | 55 | std::ostream& operator<<(std::ostream& out, const glm::vec2 vec){ 56 | out<<"X: "< vec){ 61 | for(unsigned int i = 0; i < vec.size(); i++) 62 | out< thresh)?1.0:0.0; 37 | else threshed(i) = (val(i) > thresh)?0.0:1.0; 38 | } 39 | return threshed; 40 | } 41 | 42 | }; 43 | -------------------------------------------------------------------------------- /TinyFluid/include/src/solve.h: -------------------------------------------------------------------------------- 1 | //Full Transport Solvers 2 | namespace PDE{ 3 | using namespace Eigen; 4 | 5 | typedef SparseMatrix smat; 6 | 7 | smat GXF; //Gradient Operator X-Element 8 | smat GYF; //Gradient Operator Y-Element 9 | smat GXB; //Gradient Operator X-Element 10 | smat GYB; //Gradient Operator Y-Element 11 | smat XFLUX; //Integrated Surface Flux X, UNIFORM AREA!! 12 | smat YFLUX; 13 | 14 | Eigen::VectorXd E; 15 | 16 | smat DIFFUSIONMAT; 17 | smat TRANSPORTMAT; 18 | 19 | void initialize(double dx, double dy){ 20 | E = ArrayXd::Ones(SIZE*SIZE); 21 | 22 | //Discrete Differential Operators (of some order) 23 | GXF = space::FFD(glm::vec2(1, 0), 1)/dx; //Gradient needs to be divided by the grid-spacing 24 | GYF = space::FFD(glm::vec2(0, 1), 1)/dy; //-``- 25 | GXB = space::BFD(glm::vec2(1, 0), 1)/dx; //Gradient needs to be divided by the grid-spacing 26 | GYB = space::BFD(glm::vec2(0, 1), 1)/dy; //-``- 27 | 28 | solver.setTolerance(0.0000001); 29 | 30 | //Surface Integrators (i.e. convective fluxes over surface) 31 | XFLUX = space::FV_FLUX(glm::vec2(1, 0))/dx; 32 | YFLUX = space::FV_FLUX(glm::vec2(0, 1))/dy; 33 | 34 | //Diffusion Operator! (Note: This is in FV Form and Includes the Area / Volume!!!) 35 | DIFFUSIONMAT = space::FV_DIFFUSION(glm::vec2(1, 0))/dx/dx + space::FV_DIFFUSION(glm::vec2(0, 1))/dy/dy; 36 | } 37 | 38 | //Navier Stokes Matrices 39 | smat VMAT; 40 | smat E_MAT; 41 | smat I_MAT; 42 | VectorXd PSRCX; 43 | VectorXd PSRCY; 44 | VectorXd A; 45 | 46 | VectorXd vXG; 47 | VectorXd vYG; 48 | 49 | VectorXd dP; 50 | VectorXd dvX; 51 | VectorXd dvY; 52 | 53 | //SIMPLEC FV Algorithm 54 | void navierstokes(float dt, float viscosity, VectorXd& vX, VectorXd& vY, VectorXd& P, VectorXd& bc, glm::vec2 g, glm::vec2 vt, Eigen::VectorXd& B){ 55 | 56 | auto step = [&](){ 57 | 58 | //Non-Linear Advection Operator 59 | VMAT = -1.0*(vX.asDiagonal()*XFLUX); 60 | VMAT += -1.0*(vY.asDiagonal()*YFLUX); 61 | 62 | //Explicit Integration Matrix 63 | E_MAT = bc.asDiagonal()*(VMAT + viscosity*DIFFUSIONMAT); 64 | 65 | //Pressure Source Terms 66 | PSRCX = bc.cwiseProduct(g.x*B.cwiseProduct((E*vt.x-vX).cwiseMax(0))); 67 | PSRCX.noalias() -= bc.cwiseProduct(XFLUX*P); 68 | 69 | PSRCY = bc.cwiseProduct(g.y*B.cwiseProduct((E*vt.y-vY).cwiseMax(0))); 70 | PSRCY.noalias() -= bc.cwiseProduct(YFLUX*P); 71 | 72 | //Implicit Portion 73 | I_MAT = SE - dt*E_MAT; 74 | A = (I_MAT*E).cwiseInverse(); 75 | 76 | }; 77 | 78 | //Execute Step 79 | step(); 80 | 81 | //Crank Nicholson 82 | PDE::integrate(dt, vX, E_MAT, PSRCX); 83 | PDE::integrate(dt, vY, E_MAT, PSRCY); 84 | 85 | //Pressure Correction 86 | double newerr = 1.0; 87 | double pCorr = 1.0; 88 | int maxiter = 250; 89 | int n = 0; 90 | double err = 1.0; 91 | bool divergence = false; 92 | 93 | while(newerr > 1E-4 && pCorr > 1E-6 && !divergence && maxiter){ 94 | 95 | n++; 96 | 97 | step(); 98 | 99 | PSRCX = vX + dt*PSRCX; 100 | PSRCY = vY + dt*PSRCY; 101 | 102 | //Predict Velocity 103 | solver.compute(I_MAT); 104 | vXG = solver.solve(PSRCX); 105 | vYG = solver.solve(PSRCY); 106 | 107 | //2D Laplace Operator 108 | solver.compute((GXF*A.asDiagonal()*GXB+ GYF*A.asDiagonal()*GYB)); 109 | 110 | //Compute Error Terms 111 | dP = solver.solve((GXB*vXG + GYB*vYG)); 112 | dvX = -1.0*A.cwiseProduct(GXF*dP); 113 | dvY = -1.0*A.cwiseProduct(GYF*dP); 114 | 115 | //Pressure and Velocity Correction 116 | P.noalias() += bc.cwiseProduct(dP); 117 | vX = vXG + 0.8*bc.cwiseProduct(dvX); //Underrelax 118 | vY = vYG + 0.8*bc.cwiseProduct(dvY); 119 | 120 | //Divergence of Field as Error Quantification 121 | newerr = (GXB*vXG + GYB*vYG + dvY + dvX).squaredNorm()/(SIZE*SIZE); 122 | pCorr = dP.squaredNorm()/(SIZE*SIZE); 123 | 124 | if(newerr > err) divergence = true; 125 | maxiter--; 126 | 127 | } 128 | 129 | } 130 | 131 | void transport(double dt, double D, VectorXd& val, smat& VMAT, VectorXd& hc, VectorXd& src){ 132 | TRANSPORTMAT = hc.asDiagonal()*VMAT; 133 | TRANSPORTMAT += D*hc.asDiagonal()*DIFFUSIONMAT; 134 | PDE::integrate(dt, val, TRANSPORTMAT, src); 135 | } 136 | 137 | }; 138 | -------------------------------------------------------------------------------- /TinyFluid/include/src/space.h: -------------------------------------------------------------------------------- 1 | //Spatial Discretization 2 | namespace space{ 3 | using namespace Eigen; 4 | 5 | //Factorial Calculator 6 | double fac(int k){ 7 | int j = 1; //Factorial 8 | for(int i = 1; i <= k; i++) 9 | j*= i; 10 | return j; 11 | } 12 | 13 | //Taylor Coefficient 14 | double taylor(double x, double a, int n){ 15 | return (pow(x-a, n) / fac(n)); 16 | } 17 | 18 | /* 19 | There are three main operator types I use: 20 | 21 | - Interpolators (i.e. lagrange polynomials) 22 | - Differentiators (i.e. finite differences) 23 | - Integrators (i.e. numerical quadrature) - not implemented at the moment 24 | 25 | As they are linearizations, they can be put into general matrix form after 26 | the individual operator weights have been computed. 27 | 28 | Below are weight calculating functions for all three types of operators, as 29 | well as one general function for placing them into a sparse matrix system. 30 | */ 31 | 32 | /* 33 | Lagrange Interpolator: 34 | Setup the Vandermonde Matrix for the linear equation of the polynomial. 35 | Inversion and evaluation at point = 0 yields the linear combination of 36 | evaluated values f, that gives us point a0 (the intercept), which is 37 | our interpolated value for arbitrary polynomial degree. 38 | */ 39 | 40 | std::vector LI(std::initializer_list shift){ 41 | std::vector weights = shift; 42 | 43 | //Vandermonde Matrix 44 | int N = shift.size(); 45 | Eigen::MatrixXd V(N, N); 46 | for(int p = 0; p < N; p++) 47 | for(int d = 0; d < N; d++) 48 | V(p, d) = pow(weights[p], d); 49 | 50 | //Invert the Matrix 51 | V = V.inverse(); 52 | 53 | //Extract the 0th Row 54 | for(int i = 0; i < N; i++) 55 | weights[i] = V(0, i); 56 | 57 | return weights; 58 | } 59 | 60 | /* 61 | Finite Difference Approximator: 62 | Compute the Taylor Matrix for all points expanded around zero 63 | Invert the matrix and select the appropriate row for the weights! 64 | */ 65 | 66 | std::vector FD(std::initializer_list points, unsigned int order){ 67 | std::vector weights = points; 68 | 69 | //Check for Consistency 70 | if(order >= points.size()){ 71 | std::cout<<"Order must be strictly smaller than the number of support points."< OP(std::initializer_list _p, std::vector w, glm::ivec2 dim){ 108 | Eigen::SparseMatrix M(SIZE*SIZE, SIZE*SIZE); 109 | std::vector list; 110 | std::vector p = _p; 111 | 112 | //Loop over all Guys 113 | for(int i = 0; i < SIZE*SIZE; i++) 114 | //Loop over all Offset Positions 115 | for(unsigned int j = 0; j < p.size(); j++){ 116 | //Position of the Offset Element and add the weight to the matrix 117 | glm::ivec2 shifted = (alg::pos(i) + glm::ivec2(p[j])*dim + SIZE)%SIZE; 118 | list.push_back(triplet(i, alg::index(shifted), w[j])); 119 | } 120 | M.setFromTriplets(list.begin(), list.end()); 121 | return M; 122 | } 123 | 124 | /* 125 | ================================================================================ 126 | EXAMPLE OPERATORS FOR CONVENIENCE 127 | ================================================================================ 128 | */ 129 | 130 | /* 131 | These individual operators can be tuned to any accuracy you like. 132 | */ 133 | 134 | //Interpolate the surface values linearly on both faces in a direction! 135 | Eigen::SparseMatrix FV_FLUX(glm::vec2 dim){ 136 | std::vector w = LI({-0.5, 0.5}); 137 | return OP({0, 1}, w, dim) - OP({0, -1}, w, dim); 138 | } 139 | 140 | //1st Order Accurate Forward Finite Differences, Differential at Boundary for 141 | //both surfaces in a direction summed up! 142 | Eigen::SparseMatrix FV_DIFFUSION(glm::vec2 dim){ 143 | std::vector w1 = FD({0, 1}, 1); 144 | std::vector w2 = FD({0, -1}, 1); 145 | return OP({0, 1}, w1, dim) - OP({0, -1}, w2, dim); 146 | } 147 | 148 | //4th Order Accurate Centered Differences, Approximation of Nth order Derivative 149 | Eigen::SparseMatrix CFD(glm::vec2 dim, int n){ 150 | std::vector w = FD({-2, -1, 0, 1, 2}, n); 151 | return OP({-2, -1, 0, 1, 2}, w, dim); 152 | } 153 | 154 | //Forward Finite Differences 155 | Eigen::SparseMatrix FFD(glm::vec2 dim, int n){ 156 | std::vector w = FD({0, 1}, n); 157 | return OP({0, 1}, w, dim); 158 | } 159 | 160 | //Forward Finite Differences 161 | Eigen::SparseMatrix BFD(glm::vec2 dim, int n){ 162 | std::vector w = FD({0, 1}, n); 163 | return OP({-1, 0}, w, dim); 164 | } 165 | 166 | //Forward Finite Differences 167 | Eigen::SparseMatrix SFD(glm::vec2 dim, int n){ 168 | std::vector w = FD({-1, 0, 1}, n); 169 | return OP({-1, 0, 1}, w, dim); 170 | } 171 | 172 | }; //End of Namespace 173 | -------------------------------------------------------------------------------- /TinyFluid/include/src/time.h: -------------------------------------------------------------------------------- 1 | //Time Integrators 2 | namespace PDE{ 3 | using namespace Eigen; 4 | typedef SparseMatrix smat; 5 | 6 | enum Integrator{ 7 | EE, //Explicit Euler 8 | IE, //Implicit Euler 9 | CN, //Crank-Nicholson 10 | PI //Point-Implicit 11 | }; 12 | 13 | //To-Do: General Multi-Step Integrators 14 | 15 | BiCGSTAB> solver; 16 | SparseMatrix SE = alg::sparseIdentity(); 17 | 18 | /* Pure Implicit / Explicit / Defined Mixture */ 19 | template 20 | void integrate(double dt, VectorXd& val, smat& mat){ 21 | std::cout<<"Please specify an integration method."< 26 | void integrate(double dt, VectorXd& val, smat& mat, VectorXd& src){ 27 | std::cout<<"Please specify an integration method."< 32 | void integrate(double dt, VectorXd& val, smat& mat_E, smat& mat_I){ 33 | std::cout<<"Please specify an integration method."< 38 | void integrate(double dt, VectorXd& val, smat& mat_E, smat& mat_I, VectorXd& src){ 39 | std::cout<<"Please specify an integration method."< 45 | void integrate(double dt, VectorXd& val, smat& mat){ 46 | val.noalias() += dt*(mat*val); 47 | } 48 | 49 | template<> 50 | void integrate(double dt, VectorXd& val, smat& mat, VectorXd& src){ 51 | val.noalias() += dt*(mat*val); 52 | val.noalias() += dt*src; 53 | } 54 | 55 | /* Implicit Euler Integrator - Fully Implicit */ 56 | 57 | template<> 58 | void integrate(double dt, VectorXd& val, smat& mat){ 59 | solver.compute(SE-dt*mat); 60 | val= solver.solve(val); 61 | } 62 | 63 | template<> 64 | void integrate(double dt, VectorXd& val, smat& mat, VectorXd& source){ 65 | solver.compute(SE-dt*mat); 66 | val = solver.solve(val + dt*source); 67 | } 68 | 69 | /* Crank-Nicholson Integrator - Semi Explicit / Implicit */ 70 | 71 | template<> 72 | void integrate(double dt, VectorXd& val, smat& mat){ 73 | integrate(0.5*dt, val, mat); //Perform Explicit Half-Step 74 | integrate(0.5*dt, val, mat); //Perform Implicit Half-Step 75 | } 76 | 77 | template<> 78 | void integrate(double dt, VectorXd& val, smat& mat, VectorXd& source){ 79 | integrate(0.5*dt, val, mat, source); //Perform Explicit Half-Step 80 | integrate(0.5*dt, val, mat, source); //Perform Implicit Half-Step 81 | } 82 | 83 | /* Point-Implicit Integrator */ 84 | 85 | template<> 86 | void integrate(double dt, VectorXd& val, smat& mat_E, smat& mat_I){ 87 | integrate(dt, val, mat_E); //Perform Explicit Integration 88 | integrate(dt, val, mat_I); //Perform Implicit Half-Step 89 | } 90 | 91 | template<> 92 | void integrate(double dt, VectorXd& val, smat& mat_E, smat& mat_I, VectorXd& source){ 93 | integrate(dt, val, mat_E, source); //Perform Explicit Integration 94 | integrate(dt, val, mat_I, source); //Perform Implicit Half-Step 95 | } 96 | 97 | //End of Namespace 98 | }; 99 | -------------------------------------------------------------------------------- /include/model.h: -------------------------------------------------------------------------------- 1 | //Model Stuff 2 | int SEED = 10; 3 | double scale = 15.0; 4 | glm::vec2 dim = glm::vec2(100); 5 | noise::module::Perlin perlin; 6 | 7 | //View Stuff 8 | const int WIDTH = 1200; 9 | const int HEIGHT = 800; 10 | 11 | glm::vec3 viewPos = glm::vec3(50, 0, 50); 12 | float zoom = 0.1; 13 | float zoomInc = 0.001; 14 | float rotation = 0.0f; 15 | glm::vec3 cameraPos = glm::vec3(50, 60, 50); 16 | glm::vec3 lookPos = glm::vec3(0, 10, 0); 17 | glm::mat4 camera = glm::lookAt(cameraPos, lookPos, glm::vec3(0,1,0)); 18 | glm::mat4 projection = glm::ortho(-(float)WIDTH*zoom, (float)WIDTH*zoom, -(float)HEIGHT*zoom, (float)HEIGHT*zoom, -800.0f, 500.0f); 19 | 20 | glm::vec3 lightPos = glm::vec3(-100.0f, 100.0f, -150.0f); 21 | 22 | glm::mat4 depthModelMatrix = glm::mat4(1.0); 23 | glm::mat4 depthProjection = glm::ortho(-300, 300, -300, 300, 0, 800); 24 | glm::mat4 depthCamera = glm::lookAt(lightPos, glm::vec3(0), glm::vec3(0,1,0)); 25 | 26 | glm::mat4 biasMatrix = glm::mat4( 27 | 0.5, 0.0, 0.0, 0.0, 28 | 0.0, 0.5, 0.0, 0.0, 29 | 0.0, 0.0, 0.5, 0.0, 30 | 0.5, 0.5, 0.5, 1.0 31 | ); 32 | 33 | std::function constructor = [&](Model* m, double* D){ 34 | 35 | //Clear the Containers 36 | m->indices.clear(); 37 | m->positions.clear(); 38 | m->normals.clear(); 39 | m->colors.clear(); 40 | 41 | int w = dim.y; 42 | 43 | //Loop over all positions and add the triangles! 44 | for(int i = 0; i < dim.x-1; i++){ 45 | for(int j = 0; j < dim.y-1; j++){ 46 | 47 | //Add to Position Vector 48 | glm::vec3 b = glm::vec3(i, scale*D[i*w+j], j); 49 | glm::vec3 a = glm::vec3(i+1, scale*D[(i+1)*w+j], j); 50 | glm::vec3 d = glm::vec3(i, scale*D[i*w+j+1], j+1); 51 | glm::vec3 c = glm::vec3(i+1, scale*D[(i+1)*w+j+1], j+1); 52 | 53 | //Add Indices 54 | m->indices.push_back(m->positions.size()/3+0); 55 | m->indices.push_back(m->positions.size()/3+1); 56 | m->indices.push_back(m->positions.size()/3+2); 57 | 58 | m->positions.push_back(a.x); 59 | m->positions.push_back(a.y); 60 | m->positions.push_back(a.z); 61 | m->positions.push_back(b.x); 62 | m->positions.push_back(b.y); 63 | m->positions.push_back(b.z); 64 | m->positions.push_back(c.x); 65 | m->positions.push_back(c.y); 66 | m->positions.push_back(c.z); 67 | 68 | glm::vec3 n1 = -glm::normalize(glm::cross(a-b, c-b)); 69 | 70 | for(int i = 0; i < 3; i++){ 71 | m->normals.push_back(n1.x); 72 | m->normals.push_back(n1.y); 73 | m->normals.push_back(n1.z); 74 | } 75 | 76 | m->indices.push_back(m->positions.size()/3+0); 77 | m->indices.push_back(m->positions.size()/3+1); 78 | m->indices.push_back(m->positions.size()/3+2); 79 | 80 | m->positions.push_back(d.x); 81 | m->positions.push_back(d.y); 82 | m->positions.push_back(d.z); 83 | m->positions.push_back(c.x); 84 | m->positions.push_back(c.y); 85 | m->positions.push_back(c.z); 86 | m->positions.push_back(b.x); 87 | m->positions.push_back(b.y); 88 | m->positions.push_back(b.z); 89 | 90 | glm::vec3 n2 = -glm::normalize(glm::cross(d-c, b-c)); 91 | 92 | for(int i = 0; i < 3; i++){ 93 | m->normals.push_back(n2.x); 94 | m->normals.push_back(n2.y); 95 | m->normals.push_back(n2.z); 96 | } 97 | } 98 | } 99 | }; 100 | -------------------------------------------------------------------------------- /include/source.h: -------------------------------------------------------------------------------- 1 | /* 2 | Physical Source Terms 3 | 4 | Desirable Terms: 5 | - Henry's Law for Vapor equilibrium concentration 6 | - Raoults Law for Determining Phase Fraction! 7 | - Thin Film Mass Transfer Law 8 | - Sun Heating (Flat or Radial) 9 | - 10 | */ 11 | 12 | namespace source{ 13 | 14 | Eigen::ArrayXd E = Eigen::ArrayXd::Ones(SIZE*SIZE); 15 | 16 | Eigen::ArrayXd Psat(Eigen::VectorXd& P, Eigen::VectorXd& T){ 17 | Eigen::ArrayXd _psat = Eigen::ArrayXd::Ones(SIZE*SIZE); 18 | for(int i = 0; i < SIZE*SIZE; i++) 19 | _psat(i) = pow(10.0, 8.07131 - 1730.63/(233.426+T(i))); 20 | return _psat*101325.0/760.0; 21 | } 22 | 23 | Eigen::ArrayXd Ps; 24 | 25 | //How do clouds look? 26 | Eigen::ArrayXd CLOUD(Eigen::VectorXd& H, Eigen::VectorXd& P, Eigen::VectorXd& T, double thresh){ 27 | return 0.9*(thresh*E-(Psat(P, T)-H.array()*P.array()).cwiseMin(thresh))/thresh; //It is possible to be "oversaturated" 28 | } 29 | 30 | Eigen::ArrayXd G = shape::flatGaussian(glm::vec2(SIZE/2.0, SIZE/2.0), glm::vec2(SIZE*15.0, SIZE*2.0)); 31 | 32 | Eigen::VectorXd TSOURCE(Eigen::VectorXd &B, Eigen::VectorXd& height, double s, Eigen::VectorXd& H, Eigen::VectorXd& P, Eigen::VectorXd& T, Eigen::VectorXd& vX, Eigen::VectorXd& vY){ 33 | 34 | Eigen::ArrayXd DP = Ps-H.array()*P.array(); 35 | 36 | //Evaporation Cooling (MORE!) 37 | const double m = 0.001; 38 | Eigen::ArrayXd Z = -50000.0*m*DP.cwiseMax(0.0)*(s*E-height.array().cwiseMin(s))/Ps; 39 | 40 | //Rain Removal 41 | const double thresh = 75.0; //This is the oversaturation capacity 42 | const double k = 0.0001; 43 | Z += 1000.0*k*(DP.cwiseMin(thresh)-E*thresh); 44 | 45 | //Boundary Volume Not Height Difference... (Increase proportionally to the temperature...) 46 | Z -= 30.0*0.5*(vX.cwiseProduct((PDE::GXF+PDE::GXB)*height.cwiseMax(s)) + vY.cwiseProduct((PDE::GYF+PDE::GYB)*height.cwiseMax(s))).array(); 47 | 48 | //Radiation Transfer (Get Albedo and Radiation Balance Steady State T) 49 | Z += 0.1*(10*E + 15*G - T.array())*(E-CLOUD(H, P, T, 250.0)); 50 | 51 | return Z; 52 | } 53 | 54 | Eigen::ArrayXd HSOURCE(Eigen::VectorXd& B, Eigen::VectorXd& height, double s, Eigen::VectorXd& H, Eigen::VectorXd& P, Eigen::VectorXd& T){ 55 | 56 | //Compute Psat one time! (call hsource before tsource) 57 | Ps = Psat(P, T); 58 | 59 | //Mass Transfer Addition.. 60 | //Evaporation Mass Transfer (k = approach rate to th equilibrium concentration) 61 | const double m = 0.001; 62 | Eigen::ArrayXd Z = m*(Ps-H.array()*P.array()).cwiseMax(0.1)*B.array()/Ps; 63 | 64 | //Rain Removal 65 | const double thresh = 75.0; //This is the oversaturation capacity! 66 | const double k = 0.0001; 67 | Z += -k*E*thresh + k*(Ps-H.array()*P.array()).cwiseMin(thresh); 68 | 69 | return Z; 70 | } 71 | }; 72 | -------------------------------------------------------------------------------- /include/terrain.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace Eigen; 4 | 5 | class Field{ 6 | public: 7 | //Grid-Size 8 | double dx = 1.0/(double)SIZE; 9 | double dy = 1.0/(double)SIZE; 10 | double dt = 0.025; 11 | 12 | //Parameters 13 | double viscosity = 0.001; //[m^2/s] //Future: Replace with Temperature Dependent? 14 | double density = 1.225; //[kg/m^3]Future: Replace with Temperature Dependent? 15 | double P0 = 1E+5; //Initial Pressure [Pa] 16 | 17 | int SEED = 0; 18 | 19 | //Volume Force 20 | glm::vec2 g = glm::vec2(1.0, 1.0); 21 | glm::vec2 v0 = glm::vec2(1.0, 0.0); //Terminal Velocity at Driving Force 22 | 23 | float sealevel; 24 | 25 | //Integration Stuff 26 | void initialize(); 27 | void timestep(); 28 | int count = 0; 29 | bool divergence = false; 30 | double err = 100.0; //Initial Mass Error 31 | 32 | //Velocities (Actually) 33 | VectorXd vX; 34 | VectorXd vY; 35 | VectorXd P; 36 | VectorXd height; 37 | VectorXd bc; 38 | VectorXd humidity; 39 | VectorXd temperature; 40 | double H0 = 0.01; //Initial Humidity 41 | double T0 = 25.0; //Celsius 42 | 43 | //If these two guys are too large, the disturbances propagate like a wave 44 | //i.e. elliptically instead of characteristically 45 | //If their ratio is too different, then one propagates too fast or too slow 46 | //Meaning you get these huge eliminations or no spread of rain nucleation 47 | double diffusivity = 0.0004; 48 | double conductivity = 0.0008; //Important: Diffusivity Lower than Conductivity (Slightly) 49 | }; 50 | 51 | VectorXd hc = ArrayXd::Zero(SIZE*SIZE); 52 | VectorXd b1 = ArrayXd::Zero(SIZE*SIZE); 53 | VectorXd b2 = ArrayXd::Zero(SIZE*SIZE); 54 | 55 | VectorXd B; 56 | 57 | void Field::initialize(){ 58 | 59 | srand(time(NULL)); 60 | SEED = 100;//rand(); 61 | std::cout< sealevel)?hc(i)*0.3:1.0; 89 | } 90 | 91 | //Square it for more emphasis on choking effect 92 | bc = bc.cwiseProduct(bc); 93 | 94 | //Simple Double Counter-Current Flow 95 | double k; 96 | k = (SEED % 2 == 0)?1.0:-1.0; 97 | b1 += (k*shape::flatGaussian(glm::vec2(0.0, SIZE/2.0), SIZE/2.0)).matrix(); 98 | b1 += (k*shape::flatGaussian(glm::vec2(SIZE, SIZE/2.0), SIZE/2.0)).matrix(); 99 | //Only half as fast at the top... 100 | b2 -= (k*0.2*shape::flatGaussian(glm::vec2(SIZE/2.0, 0.0), SIZE/2.0)).matrix(); 101 | b2 -= (k*0.2*shape::flatGaussian(glm::vec2(SIZE/2.0, SIZE), SIZE/2.0)).matrix(); 102 | 103 | //Set humidity 104 | humidity = 0.0*E; 105 | temperature = T0*E; 106 | 107 | //Initialize Pressure to some pressures pike in the center... 108 | P = P0*E; 109 | 110 | //Initialize Velocities to Zero 111 | vX = ArrayXd::Zero(SIZE*SIZE); 112 | vY = ArrayXd::Zero(SIZE*SIZE); 113 | vX = bc.asDiagonal()*vX; 114 | vY = bc.asDiagonal()*vY; 115 | 116 | B = b1 + b2; 117 | 118 | //Important! 119 | PDE::initialize(dx, dy); 120 | } 121 | 122 | VectorXd HSOURCE; 123 | VectorXd TSOURCE; 124 | 125 | void Field::timestep(){ 126 | 127 | //Rotate Blower 128 | int time = 365; 129 | if(count++ >= time) count = 0; 130 | float t = 2.0*3.14159265*(count%time)/(double)time; 131 | v0 = glm::vec2(sin(t), cos(t)); 132 | 133 | //Solve the Navier Stokes Equations 134 | PDE::navierstokes(dt, viscosity, vX, vY, P, bc, g, v0, B); 135 | 136 | //Transport Species 137 | HSOURCE = source::HSOURCE(bc, height, sealevel, humidity, P, temperature); 138 | PDE::transport(dt, diffusivity, humidity, PDE::VMAT, hc, HSOURCE); 139 | humidity = humidity.cwiseMax(0.0); 140 | 141 | TSOURCE = source::TSOURCE(bc, height, sealevel, humidity, P, temperature, vX, vY); 142 | PDE::transport(dt, conductivity, temperature, PDE::VMAT, hc, TSOURCE); 143 | temperature = temperature.cwiseMax(0.0); 144 | 145 | } 146 | -------------------------------------------------------------------------------- /makefile: -------------------------------------------------------------------------------- 1 | OBJS = MicroClimate.cpp 2 | 3 | #Tiny Engine Stuff 4 | TP = TinyEngine 5 | TINY = $(TP)/include/imgui/imgui.cpp $(TP)/include/imgui/imgui_demo.cpp $(TP)/include/imgui/imgui_draw.cpp $(TP)/include/imgui/imgui_widgets.cpp $(TP)/include/imgui/imgui_impl_opengl3.cpp $(TP)/include/imgui/imgui_impl_sdl.cpp 6 | TINYLINK = -lX11 -lpthread -lSDL2 -lSDL2_image -lSDL2_mixer -lSDL2_ttf -lGL -lGLEW -lboost_serialization -lboost_system -lboost_filesystem 7 | 8 | #Optimize Flag Important for Eigen 9 | CC = g++ -std=c++17 10 | COMPILER_FLAGS = -Wfatal-errors -O3 11 | 12 | #Note Additional Dependencies Here 13 | LINKER_FLAGS = -I/usr/local/include -L/usr/local/lib -lnoise -fopenmp 14 | OBJ_NAME = main 15 | 16 | all: $(OBJS) 17 | $(CC) $(OBJS) $(TINY) $(COMPILER_FLAGS) $(LINKER_FLAGS) $(TINYLINK) -o $(OBJ_NAME) 18 | -------------------------------------------------------------------------------- /shader/default.fs: -------------------------------------------------------------------------------- 1 | #version 330 core 2 | //Lighting Settings 3 | vec3 lightCol = vec3(0.9); 4 | uniform vec3 lightPos; 5 | uniform vec3 lookDir; 6 | uniform float lightStrength = 0.2; 7 | 8 | //Sampler for the ShadowMap 9 | uniform sampler2D shadowMap; 10 | 11 | in vdata2{ 12 | flat float cloud; 13 | vec3 normal; 14 | vec4 shadow; 15 | vec3 model; 16 | vec3 y; 17 | } exg; 18 | 19 | out vec4 fragColor; 20 | 21 | int viewmode = 0; 22 | 23 | uniform bool cloudpass; 24 | 25 | //Sample a grid.. 26 | float gridSample(int size){ 27 | //Stuff 28 | float shadow = 0.0; 29 | float currentDepth = exg.shadow.z; 30 | 31 | //Compute Bias 32 | float m = 1-dot(exg.normal, normalize(lightPos)); 33 | float bias = mix(0.002, 0.2*m, pow(m, 5)); 34 | 35 | for(int x = -size; x <= size; ++x){ 36 | for(int y = -size; y <= size; ++y){ 37 | float pcfDepth = texture(shadowMap, exg.shadow.xy + vec2(x, y) / textureSize(shadowMap, 0)).r; 38 | shadow += currentDepth - 0.001 > pcfDepth ? 1.0 : 0.0; 39 | } 40 | } 41 | //Normalize 42 | shadow/=12.0; 43 | return shadow; 44 | } 45 | 46 | vec4 shade(){ 47 | //Shadow Value 48 | float shadow = 0.0; 49 | if(greaterThanEqual(exg.shadow.xy, vec2(0.0f)) == bvec2(true) && lessThanEqual(exg.shadow.xy, vec2(1.0f)) == bvec2(true)) 50 | shadow = gridSample(1); 51 | 52 | //Sample the Shadow Value from Texture 53 | return vec4(vec3(1.0-shadow), 1.0f); 54 | } 55 | 56 | vec4 phong(){ 57 | float diffuse = 2*max(dot(exg.normal, normalize(lightPos)), 0.0); 58 | float ambient = 0.2; 59 | float spec = pow(max(dot(normalize(lookDir), reflect(lightPos, exg.normal)), 0.0), 4.0); 60 | spec = 0.01 * spec; 61 | 62 | vec3 color = vec3(1); 63 | return vec4(color*(diffuse+ambient), 1.0f); 64 | } 65 | 66 | vec3 flatColor = vec3(0.40, 0.60, 0.25); 67 | vec3 waterColor = vec3(0.17, 0.40, 0.44); 68 | vec3 deepColor = vec3(0.17, 0.3, 0.3); 69 | 70 | uniform float sealevel; 71 | 72 | void main(void) { 73 | 74 | if(exg.model.y <= sealevel*15) 75 | fragColor = shade()*vec4(mix(waterColor,deepColor,0), 1.0);//phong()*vec4(color, 1.0); 76 | else 77 | fragColor = shade()*phong()*vec4(flatColor, 1.0);//phong()*vec4(color, 1.0); 78 | 79 | fragColor = mix(fragColor, vec4(vec3(0), 1), 0.8*exg.cloud);//vec4(vec3(ex_Cloud), 1.0); 80 | 81 | if(length(exg.model.xz) > 49 ) 82 | discard; 83 | 84 | if(cloudpass) 85 | fragColor = vec4(vec3(1), exg.cloud); 86 | } 87 | -------------------------------------------------------------------------------- /shader/default.gs: -------------------------------------------------------------------------------- 1 | #version 330 core 2 | layout (triangles) in; 3 | layout (triangle_strip, max_vertices = 6) out; 4 | 5 | in vdata{ 6 | flat float cloud; 7 | vec3 normal; 8 | vec4 shadow; 9 | vec3 model; 10 | } exv[]; 11 | 12 | vec4 explode(vec4 p, vec3 n){ 13 | return p+0.1*vec4(normalize(n), 1.0); 14 | } 15 | 16 | out vdata2{ 17 | flat float cloud; 18 | vec3 normal; 19 | vec4 shadow; 20 | vec3 model; 21 | vec3 y; 22 | } exg; 23 | 24 | 25 | void main() { 26 | exg.normal = exv[0].normal; 27 | exg.cloud = exv[0].cloud; 28 | exg.shadow = exv[0].shadow; 29 | exg.model = exv[0].model; 30 | exg.y = vec3(gl_in[0].gl_Position.z, gl_in[1].gl_Position.z, gl_in[2].gl_Position.z); 31 | 32 | gl_Position = gl_in[0].gl_Position; 33 | EmitVertex(); 34 | gl_Position = gl_in[1].gl_Position; 35 | EmitVertex(); 36 | gl_Position = gl_in[2].gl_Position; 37 | 38 | 39 | EmitVertex(); 40 | EndPrimitive(); 41 | 42 | } 43 | -------------------------------------------------------------------------------- /shader/default.vs: -------------------------------------------------------------------------------- 1 | #version 330 core 2 | layout (location = 0) in vec3 in_Position; 3 | layout (location = 1) in vec3 in_Normal; 4 | layout (location = 2) in vec4 in_Color; 5 | layout (location = 3) in float in_Cloud; 6 | 7 | //Lighting 8 | uniform vec3 lightPos; 9 | uniform vec3 lookDir; 10 | 11 | //Uniforms 12 | uniform mat4 model; 13 | uniform mat4 vp; 14 | uniform mat4 dbmvp; 15 | 16 | out vdata{ 17 | flat float cloud; 18 | vec3 normal; 19 | vec4 shadow; 20 | vec3 model; 21 | } exv; 22 | 23 | uniform float sealevel; 24 | uniform bool cloudpass; 25 | 26 | void main(void) { 27 | exv.cloud = in_Cloud; 28 | exv.model = (model * vec4(in_Position, 1.0f)).xyz; 29 | 30 | if(exv.model.y < sealevel*15){ 31 | exv.model.y = sealevel*15; 32 | 33 | } 34 | 35 | if(cloudpass) 36 | exv.model.y += 5.0; 37 | 38 | 39 | exv.normal = in_Normal; 40 | exv.shadow= dbmvp * vec4(exv.model, 1.0f); 41 | gl_Position = vp * vec4(exv.model, 1.0f); 42 | 43 | //ex_Color = in_Color; 44 | //ex_Position = ((gl_Position.xyz / gl_Position.w).xy * 0.5 + 0.5 ); 45 | } 46 | -------------------------------------------------------------------------------- /shader/depth.fs: -------------------------------------------------------------------------------- 1 | #version 330 core 2 | void main() { 3 | //...there appears to be nothing here... 4 | } 5 | -------------------------------------------------------------------------------- /shader/depth.vs: -------------------------------------------------------------------------------- 1 | #version 330 core 2 | 3 | layout (location = 0) in vec3 in_Position; 4 | uniform mat4 dmvp; 5 | 6 | void main(void) { 7 | gl_Position = dmvp * vec4(in_Position, 1.0f); 8 | } 9 | --------------------------------------------------------------------------------