39 uint8_t
r = 0,
g = 0,
b = 0,
a = 255;
54 return {c.
r, c.
g, c.
b, c.
a};
57 return {c.
r, c.g, c.b, c.a};
62 return {uint8_t(c >> 24), uint8_t(c >> 16), uint8_t(c >> 8), uint8_t(c)};
69 t = std::clamp(t, 0.0f, 1.0f);
70 return from_rl(ColorFromHSV((1.0f - t) * 240.0f, 1.0f, 0.95f));
75 t = std::clamp(t, -1.0f, 1.0f);
77 auto v = uint8_t(255 * t * t);
78 return {v, 0, uint8_t(v / 10), 255};
80 auto v = uint8_t(255 * t * t);
81 return {uint8_t(v / 10), 0, v, 255};
89 float amp = std::min(1.0f,
float(std::sqrt(prob / max_prob)));
90 float hue = float((phase + 3.14159265) / (2.0 * 3.14159265)) * 360.0f;
91 float h6 = hue / 60.0f;
93 float f = h6 - int(h6);
95 float p = amp * (1.0f - s);
96 float q = amp * (1.0f - s * f);
97 float u = amp * (1.0f - s * (1.0f - f));
131 return {uint8_t(r * 255), uint8_t(g * 255), uint8_t(b * 255), 255};
136 t = std::clamp(t, 0.0f, 1.0f);
138 uint8_t(a.
r + t * (b.
r - a.
r)),
139 uint8_t(a.
g + t * (b.
g - a.
g)),
140 uint8_t(a.
b + t * (b.
b - a.
b)),
141 uint8_t(a.
a + t * (b.
a - a.
a)),
159 buf.assign(n * n, ::BLACK);
160 Image img = GenImageColor(n, n, ::BLACK);
161 tex = LoadTextureFromImage(img);
200 return IsKeyPressed(KEY_R);
204 void dot(
float x,
float y,
Color c,
float r = 3.0f) {
205 DrawCircleV({x, y}, r,
to_rl(c));
208 DrawCircleLines(
int(x),
int(y), r,
to_rl(c));
215 float thick = 1.0f) {
216 DrawLineEx({x0, y0}, {x1, y1}, thick,
to_rl(c));
218 void rect(
float x,
float y,
float w,
float h,
Color c) {
219 DrawRectangleV({x, y}, {w, h},
to_rl(c));
226 float thick = 1.0f) {
227 DrawRectangleLinesEx({x, y, w, h}, thick,
to_rl(c));
229 void text(
const char* s,
float x,
float y,
int sz,
Color c) {
230 DrawText(s,
int(x),
int(y), sz,
to_rl(c));
234 void textf(
float x,
float y,
int sz,
Color c,
const char* fmt, ...) {
238 vsnprintf(buf,
sizeof(buf), fmt, args);
240 DrawText(buf,
int(x),
int(y), sz,
to_rl(c));
250 for (
int row = 0; row < N; ++row)
251 for (
int col = 0; col < N; ++col)
252 cv.buf[row * N + col] =
to_rl(color_fn(col, row));
253 UpdateTexture(cv.tex, cv.buf.data());
254 DrawTexturePro(cv.tex,
255 {0, 0, float(N), float(N)},
256 {0, 0, float(width), float(height)},
264 void slider(
const char* label,
double lo,
double hi,
double& val) {
265 constexpr int PAD = 10;
266 constexpr int SLOT_H = 38;
267 constexpr int BAR_W = 220;
268 constexpr int BAR_H = 8;
273 DrawRectangle(X - 4, Y - 2, BAR_W + 8, SLOT_H - 4, {0, 0, 0, 170});
274 DrawRectangle(X, Y + 18, BAR_W, BAR_H, {80, 80, 80, 220});
276 float t = std::clamp(
float((val - lo) / (hi - lo)), 0.0f, 1.0f);
277 int tx = X + int(t * BAR_W);
279 Vector2 mp = GetMousePosition();
280 Rectangle hit = {float(X), float(Y), float(BAR_W), float(SLOT_H)};
281 if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)
282 && CheckCollisionPointRec(mp, hit)) {
283 t = std::clamp((mp.x - X) / BAR_W, 0.0f, 1.0f);
284 val = lo + t * (hi - lo);
285 tx = X + int(t * BAR_W);
288 DrawCircle(tx, Y + 18 + BAR_H / 2, 9, {200, 200, 200, 240});
289 DrawText(TextFormat(
"%s: %.3g", label, val),
293 {210, 210, 210, 230});
308 c.position = {cam.
px, cam.
py, cam.
pz};
309 c.target = {cam.
tx, cam.
ty, cam.
tz};
310 c.up = {cam.
ux, cam.
uy, cam.
uz};
312 c.projection = CAMERA_PERSPECTIVE;
320 DrawSphere({x, y, z}, r,
to_rl(c));
323 DrawSphereWires({x, y, z}, r, 6, 6,
to_rl(c));
332 DrawLine3D({x0, y0, z0}, {x1, y1, z1},
to_rl(c));
335 cube3d(
float x,
float y,
float z,
float sx,
float sy,
float sz,
Color c) {
336 DrawCube({x, y, z}, sx, sy, sz,
to_rl(c));
347template<
class DrawFn>
348void run(
const char* title,
352 Color bg = {15, 15, 15, 255}) {
353 SetConfigFlags(FLAG_MSAA_4X_HINT);
354 InitWindow(w, h, title);
358 Frame frame{w, h, state.paused, state.substeps, state};
360 while (!WindowShouldClose()) {
361 if (IsKeyPressed(KEY_SPACE))
362 state.paused = !state.paused;
363 if (IsKeyPressed(KEY_EQUAL) || IsKeyPressed(KEY_KP_ADD))
364 state.substeps = std::min(state.substeps + 1, 16);
365 if (IsKeyPressed(KEY_MINUS) || IsKeyPressed(KEY_KP_SUBTRACT))
366 state.substeps = std::max(state.substeps - 1, 1);
368 state.slider_count = 0;
371 ClearBackground(
to_rl(bg));
376 DrawRectangle(w / 2 - 70, h / 2 - 18, 140, 36, {0, 0, 0, 160});
377 DrawText(
"PAUSED", w / 2 - 46, h / 2 - 10, 24, ::YELLOW);
383 state.canvas.unload();
Color lerp_color(Color a, Color b, float t)
Linear blend between two colors.
void run(const char *title, int w, int h, DrawFn draw, Color bg={15, 15, 15, 255})
Color phase_hsv_color(double prob, double phase, double max_prob)
Quantum wavefunction: hue = phase, brightness = sqrt(|psi|^2 / max).
Color heat_color(float t)
t in [0,1]: blue -> cyan -> yellow -> red.
Color diverging_color(float t)
t in [-1,1]: deep blue -> black -> deep red.
inline ::Color to_rl(Color c)
void dot(float x, float y, Color c, float r=3.0f)
void line(float x0, float y0, float x1, float y1, Color c, float thick=1.0f)
void field(int N, Fn color_fn)
void sphere3d_wire(float x, float y, float z, float r, Color c)
void cube3d(float x, float y, float z, float sx, float sy, float sz, Color c)
void rect_outline(float x, float y, float w, float h, Color c, float thick=1.0f)
void slider(const char *label, double lo, double hi, double &val)
void line3d(float x0, float y0, float z0, float x1, float y1, float z1, Color c)
bool reset_pressed() const
void textf(float x, float y, int sz, Color c, const char *fmt,...)
void sphere3d(float x, float y, float z, float r, Color c)
void text(const char *s, float x, float y, int sz, Color c)
void circle(float x, float y, float r, Color c)
void rect(float x, float y, float w, float h, Color c)
std::vector<::Color > buf