Files
egutierrez c967c2edfd feat(viz): renderer shapes/iconos/flechas/edge-styles (issue 0049f)
graph_renderer 1.5.0:
- 6 shapes SDF (circle, square, diamond, hex, triangle, rounded square)
  con dispatch en fragment shader y AA via fwidth.
- Atlas opcional de iconos Tabler bakeado por graph_icons; el shader
  compone overlay desde un uniform vec4 u_icon_uvs[256]. Setter publico
  graph_renderer_set_icon_atlas(r, tex, uv_table, count).
- Aristas direccionales: 6 vertices por arista (line + chevron de la
  flecha) en una sola draw call; segmento principal acortado por el
  radio del nodo target.
- Edge styles solid/dashed/dotted via descarte por arc_length en el
  fragment shader; las lineas del chevron son siempre solidas.

graph_icons 1.0.0 (nuevo):
- Atlas RGBA8 512x512 = grid 16x16 (256 iconos max) bakeado con
  stb_truetype desde tabler-icons.ttf.
- API: graph_icons_build/texture/region/uv_table/destroy. icon_id es
  1-based; 0 reservado para "sin icono".
- Hook FN_GRAPH_ICONS_SKIP_GL=1 para tests sin contexto GL.

Demo demos_graph_styles en primitives_gallery: 6 EntityTypes (uno por
shape) con icono Tabler representativo + 3 RelationTypes (knows/uses/
owns) con flechas direccionales y los 3 estilos.

test_graph_icons: 6 casos cubriendo bake, regiones 1-indexed, uv_table
consistente, layout en grid 16x16, validacion de count fuera de rango,
y verificacion de alpha != 0 en las celdas tras bake.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 23:01:49 +02:00

71 lines
2.9 KiB
C++

#pragma once
#include <cstdint>
struct GraphData; // forward declare
struct GraphRendererConfig {
float node_outline = 1.5f; // outline width in pixels
float edge_width = 1.0f; // edge line width
float edge_alpha = 0.4f; // edge transparency
uint32_t bg_color = 0xFF1A1A1E; // ABGR background
bool edge_fade_alpha = true; // fade edge alpha by distance to camera
// Default palette for communities (when node.color == 0)
// 10 distinct colors, ABGR packed
};
struct GraphRenderer;
// Lifecycle
GraphRenderer* graph_renderer_create(int width, int height, const GraphRendererConfig& config = {});
void graph_renderer_destroy(GraphRenderer* r);
void graph_renderer_resize(GraphRenderer* r, int width, int height);
// Render graph to internal FBO.
// cam_x, cam_y: camera center in graph space
// cam_zoom: zoom level (1.0 = 1:1 pixel mapping)
// Returns OpenGL texture ID suitable for ImGui::Image().
unsigned int graph_renderer_draw(GraphRenderer* r, const GraphData& graph,
float cam_x, float cam_y, float cam_zoom);
// Optional: bind an icon atlas built by graph_icons. The renderer composes
// icons over nodes whose `icon_id` (resolved from override or EntityType)
// is non-zero. Pass texture_id=0 to disable icons (default).
//
// `uv_table`: `count * 4` floats (u0, v0, u1, v1) per icon, 0-indexed
// (icon_id k uses uv_table[(k-1)*4..]). Must outlive the renderer or be
// re-set whenever changed (the renderer copies it into a uniform array).
void graph_renderer_set_icon_atlas(GraphRenderer* r,
unsigned int texture_id,
const float* uv_table,
int count);
// ---------------------------------------------------------------------------
// RGBA8 packing helpers
// ---------------------------------------------------------------------------
// Layout: byte 0 (LSB) = R, byte 1 = G, byte 2 = B, byte 3 (MSB) = A.
// On a little-endian host this matches GLSL's `unpackUnorm4x8(uint)` which
// returns vec4(byte0, byte1, byte2, byte3) / 255 — so the GPU reads it as
// (R, G, B, A) without any swizzle.
inline uint32_t pack_rgba8(uint8_t r, uint8_t g, uint8_t b, uint8_t a) {
return (uint32_t)r
| ((uint32_t)g << 8)
| ((uint32_t)b << 16)
| ((uint32_t)a << 24);
}
inline void unpack_rgba8(uint32_t c, uint8_t& r, uint8_t& g, uint8_t& b, uint8_t& a) {
r = (uint8_t)( c & 0xFF);
g = (uint8_t)((c >> 8 ) & 0xFF);
b = (uint8_t)((c >> 16) & 0xFF);
a = (uint8_t)((c >> 24) & 0xFF);
}
// Multiply alpha channel by a [0..1] scale, clamping to 255.
inline uint32_t modulate_alpha_rgba8(uint32_t c, float scale) {
uint32_t a = (c >> 24) & 0xFFu;
float af = (float)a * scale + 0.5f;
if (af < 0.0f) af = 0.0f;
if (af > 255.0f) af = 255.0f;
return (c & 0x00FFFFFFu) | ((uint32_t)af << 24);
}