main.c (7344B)
1 #include "gl.h" 2 3 #include <stdio.h> 4 #include <time.h> 5 #include <assert.h> 6 #ifdef NANOVG_GLEW 7 #include <GL/glew.h> 8 #endif 9 #define GLFW_INCLUDE_GLEXT 10 #include <GLFW/glfw3.h> 11 #include "nanovg/nanovg.h" 12 #define NANOVG_GL2_IMPLEMENTATION 13 #include "nanovg/nanovg_gl.h" 14 15 #include "defs.h" 16 #include "perf.h" 17 #include "demo.h" 18 #include "render.h" 19 #include "update.h" 20 #include "ln.h" 21 #include "json.h" 22 #include "options.h" 23 24 void errorcb(int error, const char *desc) 25 { 26 printf("GLFW error %d: %s\n", error, desc); 27 } 28 29 int premult = 0; 30 31 static void key(GLFWwindow *window, int key, int scancode, int action, int mods) 32 { 33 NVG_NOTUSED(scancode); 34 NVG_NOTUSED(mods); 35 if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) 36 glfwSetWindowShouldClose(window, GL_TRUE); 37 /* if (key == GLFW_KEY_SPACE && action == GLFW_PRESS) */ 38 /* blowup = !blowup; */ 39 if (key == GLFW_KEY_P && action == GLFW_PRESS) 40 premult = !premult; 41 } 42 43 static struct ln ln; 44 static double mx, my; 45 static int mdown = 0; 46 static int rmdown = 0; 47 static int mclicked = 0; 48 static int rmclicked = 0; 49 50 static const union color dark_color = { 51 .rgba = { 0x28 / 255.0, 0x2c / 255.0, 0x34 / 255.0, 1.0f } 52 }; 53 54 static const union color light_color = { 55 .rgba = { 1.0, 1.0, 1.0, 1.0f } 56 }; 57 58 59 void mouse_pos(GLFWwindow *win, double x, double y) 60 { 61 (void)win; 62 mx = x; 63 my = y; 64 } 65 66 void mouse_click(GLFWwindow *win, int button, int action, int mods) 67 { 68 (void)win; 69 (void)button; 70 (void)action; 71 (void)mods; 72 73 mclicked = action == 1 && button == 0; 74 rmclicked = action == 1 && button == 1; 75 76 if (button == 0) 77 mdown = action; 78 if (button == 1) 79 rmdown = action; 80 } 81 82 83 void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) 84 { 85 (void)mods; 86 (void)scancode; 87 (void)window; 88 89 if (action == GLFW_PRESS) { 90 switch (key) { 91 case GLFW_KEY_A: 92 ln.display_flags ^= DISP_ALIASES; 93 break; 94 case GLFW_KEY_F: 95 ln.display_flags ^= DISP_FPS; 96 break; 97 case GLFW_KEY_S: 98 ln.display_flags ^= DISP_STROKE_NODES; 99 break; 100 case GLFW_KEY_G: 101 ln.display_flags ^= DISP_GRID; 102 break; 103 case GLFW_KEY_B: 104 ln.display_flags ^= DISP_BEZIER; 105 break; 106 case GLFW_KEY_T: 107 if (ln.display_flags & DISP_DARK) 108 memcpy(&ln.clear_color, &light_color, sizeof(ln.clear_color)); 109 else 110 memcpy(&ln.clear_color, &dark_color, sizeof(ln.clear_color)); 111 ln.display_flags ^= DISP_DARK; 112 break; 113 } 114 } 115 } 116 117 static struct node *find_node(const char *pubkey, struct node *nodes, int node_count) 118 { 119 // TODO: hash table 120 for (int i = 0; i < node_count; i++) { 121 if (streq(pubkey, nodes[i].id)) 122 return &nodes[i]; 123 /* printf("%s != %s\n", pubkey, nodes[i].id); */ 124 } 125 126 return NULL; 127 } 128 129 130 static void connect_node_channels(struct node *nodes, int node_count, 131 struct channel *channels, int channel_count) 132 { 133 struct channel *chan = NULL; 134 135 for (int i = 0; i < channel_count; i++) { 136 chan = &channels[i]; 137 138 chan->nodes[0] = find_node(chan->source, nodes, node_count); 139 chan->nodes[1] = find_node(chan->destination, nodes, node_count); 140 141 assert(chan->nodes[0]); 142 assert(chan->nodes[1]); 143 } 144 } 145 146 void read_json(struct ln *ln, struct options *options) 147 { 148 FILE *channels_fd = fopen(options->channels, "r"); 149 FILE *nodes_fd = fopen(options->nodes, "r"); 150 151 int channel_count = 0; 152 int node_count = 0; 153 struct channel *channels; 154 struct node *nodes; 155 156 int res = parse_clightning_nodes(nodes_fd, &node_count, &nodes); 157 fclose(nodes_fd); 158 159 if (res != 0) { 160 printf("parse_clightning_nodes res %d\n", res); 161 exit(1); 162 } 163 164 res = parse_clightning_channels(channels_fd, &channel_count, &channels); 165 fclose(channels_fd); 166 167 if (res != 0) { 168 printf("parse_clightning_channels res %d\n", res); 169 exit(1); 170 } 171 172 printf("parsed %d nodes, %d channels\n", node_count, channel_count); 173 174 connect_node_channels(nodes, node_count, channels, channel_count); 175 ln->channels = channels; 176 ln->channel_count = channel_count; 177 ln->nodes = nodes; 178 ln->node_count = node_count; 179 } 180 181 int main(int argc, const char *argv[]) 182 { 183 GLFWwindow *window; 184 int first = 1; 185 DemoData data; 186 NVGcontext *vg = NULL; 187 PerfGraph fps; 188 double prevt = 0; 189 struct options options; 190 191 srand(0); 192 // ln collision grid subdivision 193 // cells = grid_div * grid_div 194 static const int grid_div = 20; 195 static const int dark_theme = 1; 196 197 u64 flags = DISP_DARK 198 | DISP_ALIASES 199 | DISP_GRID 200 | DISP_STROKE_NODES 201 ; 202 203 parse_options(argc, argv, &options); 204 205 read_json(&ln, &options); 206 207 ln.display_flags = flags; 208 209 if (dark_theme) 210 memcpy(&ln.clear_color, &dark_color, sizeof(ln.clear_color)); 211 else 212 memcpy(&ln.clear_color, &light_color, sizeof(ln.clear_color)); 213 214 if (!glfwInit()) { 215 printf("Failed to init GLFW."); 216 return -1; 217 } 218 219 initGraph(&fps, GRAPH_RENDER_FPS, "Frame Time"); 220 221 glfwSetErrorCallback(errorcb); 222 223 glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2); 224 glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0); 225 #ifdef DEMO_MSAA 226 glfwWindowHint(GLFW_SAMPLES, 4); 227 #endif 228 229 window = glfwCreateWindow(1000, 600, "Lightning Network Vis", NULL, NULL); 230 // window = glfwCreateWindow(1000, 600, "NanoVG", glfwGetPrimaryMonitor(), NULL); 231 if (!window) { 232 glfwTerminate(); 233 return -1; 234 } 235 236 glfwSetKeyCallback(window, key); 237 238 glfwMakeContextCurrent(window); 239 #ifdef NANOVG_GLEW 240 if (glewInit() != GLEW_OK) { 241 printf("Could not init glew.\n"); 242 return -1; 243 } 244 #endif 245 246 #ifdef DEMO_MSAA 247 vg = nvgCreateGL2(NVG_STENCIL_STROKES | NVG_DEBUG); 248 #else 249 vg = nvgCreateGL2(NVG_ANTIALIAS | NVG_STENCIL_STROKES | NVG_DEBUG); 250 #endif 251 if (vg == NULL) { 252 printf("Could not init nanovg.\n"); 253 return -1; 254 } 255 256 ln.vg = vg; 257 258 init_ln(&ln, grid_div); 259 260 if (loadDemoData(vg, &data) == -1) 261 return -1; 262 263 glfwSwapInterval(1); 264 265 glfwSetTime(0); 266 prevt = glfwGetTime(); 267 268 glfwSetKeyCallback(window, key_callback); 269 glfwSetMouseButtonCallback(window, mouse_click); 270 glfwSetCursorPosCallback(window, mouse_pos); 271 272 while (!glfwWindowShouldClose(window)) { 273 if (ln.clicked) 274 ln.clicked = 0; 275 if (ln.right_clicked) 276 ln.right_clicked = 0; 277 double t, dt; 278 int winWidth, winHeight; 279 int fbWidth, fbHeight; 280 float pxRatio; 281 282 t = glfwGetTime(); 283 dt = t - prevt; 284 prevt = t; 285 updateGraph(&fps, dt); 286 287 ln.clicked = mclicked; 288 mclicked = 0; 289 290 ln.right_clicked = rmclicked; 291 rmclicked = 0; 292 293 ln.mx = mx; 294 ln.my = my; 295 ln.mdown = mdown; 296 297 glfwGetCursorPos(window, &mx, &my); 298 glfwGetWindowSize(window, &winWidth, &winHeight); 299 300 ln.window_height = winHeight; 301 ln.window_width = winWidth; 302 303 if (first) { 304 /* random_network(winWidth, winHeight, 3, 500, &ln); */ 305 init_network(winWidth, winHeight, &ln); 306 filter_network(options.filter, NULL, &ln); 307 first = 0; 308 } 309 310 glfwGetFramebufferSize(window, &fbWidth, &fbHeight); 311 312 // Calculate pixel ration for hi-dpi devices. 313 pxRatio = (float)fbWidth / (float)winWidth; 314 315 // Update and render 316 glViewport(0, 0, fbWidth, fbHeight); 317 318 glClearColor(ln.clear_color.r, 319 ln.clear_color.g, 320 ln.clear_color.b, 321 ln.clear_color.a); 322 323 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | 324 GL_STENCIL_BUFFER_BIT); 325 326 nvgBeginFrame(vg, winWidth, winHeight, pxRatio); 327 328 /* renderDemo(vg, mx, my, winWidth, winHeight, t, 1, &data); */ 329 update(&ln, dt); 330 render_ln(&ln); 331 332 if (ln.display_flags & DISP_FPS) 333 renderGraph(vg, 5, 5, &fps); 334 335 nvgEndFrame(vg); 336 337 glfwSwapBuffers(window); 338 glfwPollEvents(); 339 } 340 341 free_ln(&ln); 342 freeDemoData(vg, &data); 343 344 nvgDeleteGL2(vg); 345 346 glfwTerminate(); 347 return 0; 348 }