diff --git a/main.c b/main.c index 07a220b..cfc48e9 100644 --- a/main.c +++ b/main.c @@ -1,11 +1,14 @@ #include "raylib.h" #include -#include - #define RAYGUI_IMPLEMENTATION #include "raygui.h" #define UI_WIDTH 400 +#define COLOR_BG (Color){ 25, 25, 30, 255 } +#define COLOR_PANEL (Color){ 40, 40, 45, 255 } +#define COLOR_ACCENT (Color){ 0, 120, 240, 255 } +#define COLOR_TEXT_DIM (Color){ 180, 180, 190, 255 } +#define COLOR_TEXT_SEC (Color){ 160, 160, 170, 255 } typedef struct { float d1; @@ -32,11 +35,19 @@ Color WavelengthToColor(float lambda) { return (Color){(unsigned char)(r * factor * 255), (unsigned char)(g * factor * 255), (unsigned char)(b * factor * 255), 255}; } +void DrawLaserBeam(Vector2 start, Vector2 end, Color color, float thickness) { + DrawLineEx(start, end, thickness * 4.0f, Fade(color, 0.15f)); + DrawLineEx(start, end, thickness * 2.0f, Fade(color, 0.4f)); + DrawLineEx(start, end, thickness, color); +} + void DrawInterferenceView(Michelson *mic, Rectangle rec) { - DrawText("ECRAN", rec.x, rec.y - 30, 20, WHITE); + DrawRectangleRec((Rectangle){rec.x - 4, rec.y - 30, rec.width + 8, rec.height + 34}, COLOR_PANEL); + //DrawText("ECRAN", rec.x, rec.y - 30, 20, WHITE); + DrawText("ECRAN", rec.x, rec.y - 26, 20, COLOR_TEXT_DIM); DrawRectangleRec(rec, BLACK); - DrawRectangleLinesEx(rec, 2, DARKGRAY); + DrawRectangleLinesEx(rec, 1, Fade(COLOR_ACCENT, 0.3f)); Color baseColor = WavelengthToColor(mic->lambda); @@ -45,6 +56,8 @@ void DrawInterferenceView(Michelson *mic, Rectangle rec) { int cx = rec.x + rec.width / 2; int cy = rec.y + rec.height / 2; + + float K = PI / mic->lambda; // Dessin pixel par pixel lent... => faire avec gpu for (int y = rec.y; y < rec.y + rec.height; y++) { @@ -53,6 +66,8 @@ void DrawInterferenceView(Michelson *mic, Rectangle rec) { float relY = (float)(y - cy); float radiusSq = relX * relX + relY * relY; + //if (radiusSq > (rec.width / 2.0f - 5) * (rec.width / 2.0f - 5)) continue; + // Diff de marche lamme d'air 2 * e cos(i) mais petits angles => cos(i) ~ 1 - i^2/2 mais i ~ r/f et r^2 = x^2 + y^2 float ringFactor = radiusSq * 0.065f; // Diff de marche dut au coin d'air @@ -61,7 +76,7 @@ void DrawInterferenceView(Michelson *mic, Rectangle rec) { float currDelta = deltaLnm - ringFactor + wDelta; // Formule de Fresnel : I = I_0 * cos^2(phi) - float phase = (PI * currDelta) / mic->lambda; + float phase = currDelta * K; float intensity = cosf(phase); intensity = intensity * intensity; @@ -70,6 +85,8 @@ void DrawInterferenceView(Michelson *mic, Rectangle rec) { DrawPixel(x, y, pixColor); } } + + DrawRectangleLinesEx(rec, 2, COLOR_PANEL); // croix centre DrawLine(cx - 10, cy, cx + 10, cy, Fade(WHITE, 0.5f)); @@ -80,37 +97,48 @@ void DrawMichelsonSchema (Michelson *mic) { Vector2 c = mic->center; Color laserColor = WavelengthToColor(mic->lambda); - float thickness = 4.0f; + float thickness = 3.0f; float sourceLen = 450.0f; float screenLen = 450.0f; float mirrorSize = 140.0f; - // Source - Vector2 startSource = {c.x - sourceLen, c.y}; - DrawLineEx(startSource, c, thickness, laserColor); - DrawRectangle(startSource.x - 20, startSource.y - 15, 20, 30, DARKGRAY); - DrawText("Source", startSource.x - 30, startSource.y - 40, 20, LIGHTGRAY); + // Laser + BeginBlendMode(BLEND_ADDITIVE); + // Source + Vector2 startSource = {c.x - sourceLen, c.y}; + DrawLaserBeam(startSource, c, laserColor, thickness); - // Miroir M2 (fixe) - Vector2 posM2 = {c.x + mic->d2, c.y}; - DrawLineEx(c, posM2, thickness, laserColor); - DrawLineEx(c, (Vector2){c.x, c.y + screenLen}, thickness, Fade(laserColor, 0.6f)); + // Miroir M2 (fixe) + Vector2 posM2 = {c.x + mic->d2, c.y}; + DrawLaserBeam(c, posM2, laserColor, thickness); + + // Miroir M1 (mobile) + Vector2 posM1 = {c.x, c.y - mic->d1}; + DrawLaserBeam(c, posM1, laserColor, thickness); + + // Projection rayon sur écran (corection tangente) + float angleRad = -(mic->angleM1 * 2.0f) * (PI / 180.0f); + float yScreen = c.y + screenLen; + float vertDist = yScreen - posM1.y; + float xOff = vertDist * tanf(angleRad); + Vector2 endPointRetour = { posM1.x + xOff, yScreen }; + DrawLaserBeam(posM1, endPointRetour, Fade(laserColor, 0.6f), thickness); + + Vector2 endPointM2 = {c.x, c.y + screenLen}; + DrawLaserBeam(c, endPointM2, Fade(laserColor, 0.5f), thickness); + EndBlendMode(); + + // Source + DrawRectangle(startSource.x - 30, startSource.y - 20, 30, 40, DARKGRAY); + DrawRectangleLines(startSource.x - 30, startSource.y - 20, 30, 40, GRAY); + DrawText("Source", startSource.x - 50, startSource.y - 50, 20, LIGHTGRAY); + + // M2 DrawRectangle(posM2.x, posM2.y - (mirrorSize / 2), 12, mirrorSize, LIGHTGRAY); DrawRectangle(posM2.x, posM2.y - (mirrorSize / 2) + 2, 4, mirrorSize - 4, WHITE); DrawText("M2", posM2.x + 20, posM2.y - 10, 20, GRAY); - // Miroir M1 (mobile) - Vector2 posM1 = {c.x, c.y - mic->d1}; - DrawLineEx(c, posM1, thickness, laserColor); - - // Projection rayon sur écran (corection tangente) - float angleRad = -(mic->angleM1 * 2.0f) * (PI / 180.0f); - float yScreen = c.y + screenLen; - float vertDist = yScreen - posM1.y; - float xOff = vertDist * tanf(angleRad); - Vector2 endPointRetour = { posM1.x + xOff, yScreen }; - DrawLineEx(posM1, endPointRetour, thickness, Fade(laserColor, 0.6f)); - + // M1 Rectangle recM1 = {posM1.x, posM1.y, mirrorSize, 12.0f}; Vector2 originM1 = {mirrorSize / 2, 6.0f}; DrawRectanglePro(recM1, originM1, mic->angleM1, LIGHTGRAY); @@ -121,68 +149,87 @@ void DrawMichelsonSchema (Michelson *mic) { // Séparatrice float sepLen = 220.0f; - Rectangle sepRec = {c.x, c.y, 4.0f, sepLen}; + Rectangle sepRec = {c.x, c.y, 6.0f, sepLen}; Vector2 sepOrigin = {2.0f, sepLen / 2}; DrawRectanglePro(sepRec, sepOrigin, -45.0f, Fade(SKYBLUE, 0.4f)); - DrawRectanglePro((Rectangle){c.x, c.y, 1.0f, sepLen}, (Vector2){0.5f, sepLen / 2}, -45.0f, Fade(WHITE, 0.5f)); + DrawRectanglePro((Rectangle){c.x, c.y, 2.0f, sepLen}, (Vector2){1.0f, sepLen / 2}, -45.0f, Fade(WHITE, 0.4f)); - DrawRectangle(c.x - 300, yScreen, 600, 15, DARKGRAY); - DrawText("Ecran", c.x - 20, yScreen + 20, 20, GRAY); + DrawRectangle(c.x - 300, yScreen, 600, 15, COLOR_PANEL); + DrawText("Ecran", c.x - 20, yScreen + 20, 20, COLOR_TEXT_DIM); } void DrawControlPanel(Michelson *mic) { - DrawRectangle(0, 0, UI_WIDTH, GetScreenHeight(), (Color){30, 30, 30, 255}); - DrawLine(UI_WIDTH, 0, UI_WIDTH, GetScreenHeight(), WHITE); + DrawRectangle(0, 0, UI_WIDTH, GetScreenHeight(), Fade(COLOR_PANEL, 0.95f)); + DrawLine(UI_WIDTH, 0, UI_WIDTH, GetScreenHeight(), Fade(WHITE, 0.1f)); int startX = 30; int startY = 30; - int buttonWidth = 60; + int buttonWidth = 70; int spacing = 20; int contentWidth = UI_WIDTH - 60; int sliderWidth = contentWidth - buttonWidth - spacing - 15; - GuiSetStyle(DEFAULT, TEXT_SIZE, 18); - GuiSetStyle(DEFAULT, BASE_COLOR_NORMAL, 0x404040FF); - GuiSetStyle(DEFAULT, BORDER_COLOR_NORMAL, 0x808080FF); - GuiSetStyle(DEFAULT, TEXT_COLOR_NORMAL, 0xFFFFFFFF); + GuiSetStyle(DEFAULT, TEXT_SIZE, 16); + GuiSetStyle(DEFAULT, BASE_COLOR_NORMAL, 0x2D2D2DFF); // Gris foncé boutons + GuiSetStyle(DEFAULT, BASE_COLOR_FOCUSED, 0x454545FF); // Gris clair hover + GuiSetStyle(DEFAULT, BASE_COLOR_PRESSED, 0x1A1A1AFF); // Très foncé click + GuiSetStyle(DEFAULT, TEXT_COLOR_NORMAL, 0xFFFFFFFF); // Texte blanc + GuiSetStyle(DEFAULT, BORDER_COLOR_NORMAL, 0x505050FF); + GuiSetStyle(DEFAULT, BORDER_COLOR_FOCUSED, 0x0078D7FF); // Bordures bleues (focus) + GuiSetStyle(DEFAULT, BACKGROUND_COLOR, 0x1E1E1EFF); DrawText("PARAMETRES", startX, startY, 30, WHITE); + DrawLine(startX, startY + 35, startX + contentWidth, startY + 35, COLOR_ACCENT); // Sliders - startY += 80; - DrawText(TextFormat("Longueur d'onde: %.0f nm", mic->lambda), startX, startY, 20, LIGHTGRAY); - GuiSlider((Rectangle){startX, startY + 30, contentWidth - 45, 30}, NULL, NULL, &mic->lambda, 380, 780); - DrawRectangle(startX + contentWidth - 35, startY + 30, 35, 30, WavelengthToColor(mic->lambda)); + startY += 70; + DrawText(TextFormat("Longueur d'onde: %.0f nm", mic->lambda), startX, startY, 20, COLOR_TEXT_SEC); + GuiSlider((Rectangle){startX, startY + 30, contentWidth - 45, 25}, NULL, NULL, &mic->lambda, 380, 780); + DrawRectangle(startX + contentWidth - 35, startY + 30, 35, 25, WavelengthToColor(mic->lambda)); - startY += 100; + startY += 90; DrawText(TextFormat("Position M1 (d1): %.1f um", mic->d1), startX, startY, 20, ORANGE); - GuiSlider((Rectangle){startX, startY + 30, sliderWidth, 30}, NULL, NULL, &mic->d1, 100, 600); - if (GuiButton((Rectangle){startX + sliderWidth + spacing + 15, startY + 30, buttonWidth, 30}, "Egal")) mic->d1 = mic->d2; + GuiSlider((Rectangle){startX, startY + 30, sliderWidth, 25}, NULL, NULL, &mic->d1, 100, 600); + if (GuiButton((Rectangle){startX + sliderWidth + spacing + 15, startY + 30, buttonWidth, 25}, "Egal")) mic->d1 = mic->d2; - startY += 100; + startY += 90; DrawText(TextFormat("Inclinaison M1: %.2f deg", mic->angleM1), startX, startY, 20, ORANGE); - GuiSlider((Rectangle){startX, startY + 30, sliderWidth, 30}, "-1", "+1", &mic->angleM1, -1.0f, 1.0f); - if (GuiButton((Rectangle){startX + sliderWidth + spacing + 15, startY + 30, buttonWidth, 30}, "0.0")) mic->angleM1 = 0.0f; + GuiSlider((Rectangle){startX, startY + 30, sliderWidth, 25}, "-1", "+1", &mic->angleM1, -1.0f, 1.0f); + if (GuiButton((Rectangle){startX + sliderWidth + spacing + 15, startY + 30, buttonWidth, 25}, "0.0")) mic->angleM1 = 0.0f; - const char* modeTxt = (fabs(mic->angleM1) < 0.01f) ? "MODE: LAME D'AIR" : "MODE: COIN D'AIR"; - Color modeColor = (fabs(mic->angleM1) < 0.01f) ? SKYBLUE : GREEN; - DrawText(modeTxt, startX, startY + 75, 20, modeColor); + bool isLameAir = (fabs(mic->angleM1) < 0.01f); + const char* modeTxt = isLameAir ? "MODE: LAME D'AIR" : "MODE: COIN D'AIR"; + Color modeColor = isLameAir ? SKYBLUE : GREEN; + + DrawRectangle(startX, startY + 70, contentWidth, 30, Fade(modeColor, 0.2f)); + DrawRectangleLines(startX, startY + 70, contentWidth, 30, modeColor); + DrawText(modeTxt, startX + 10, startY + 78, 18, modeColor); - startY += 140; - DrawRectangleLines(startX - 10, startY - 10, contentWidth + 20, 100, GRAY); - DrawText("Données", startX, startY, 20, LIGHTGRAY); + // Données + startY += 150; + DrawLine(startX, startY - 20, startX + contentWidth, startY - 20, GRAY); + DrawText("DONNEES TEMPS REEL", startX, startY, 20, GRAY); float delta = 2 * (mic->d1 - mic->d2); - DrawText(TextFormat("Delta = %.2f um", delta), startX, startY + 35, 22, WHITE); + DrawText(TextFormat("Delta = %.2f um", delta), startX, startY + 35, 20, WHITE); float p = (delta * 1000.0f) / mic->lambda; - DrawText(TextFormat("Ordre p = %.2f", p), startX, startY + 65, 22, LIGHTGRAY); + DrawText(TextFormat("Ordre p = %.2f", p), startX, startY + 65, 20, WHITE); + + int bottomY = GetScreenHeight() - 40; + DrawLine(0, bottomY, UI_WIDTH, bottomY, Fade(WHITE, 0.1f)); + + int fps = GetFPS(); + Color fpsColor = (fps >= 100) ? COLOR_ACCENT : (fps >= 60 ? GREEN : (fps >= 30 ? ORANGE : RED)); + + DrawText("STATUT:", startX, bottomY + 12, 20, COLOR_TEXT_DIM); + DrawText(TextFormat("%i FPS", fps), startX + 100, bottomY + 12, 20, fpsColor); } int main () { SetConfigFlags(FLAG_MSAA_4X_HINT); InitWindow(1920, 1080, "Interferometre de Michelson"); - SetTargetFPS(60); + SetTargetFPS(144); Michelson mic = {0}; mic.center = (Vector2){ UI_WIDTH + (1920 - UI_WIDTH) / 2.0f - 100, 1080 / 2.0f }; @@ -196,7 +243,11 @@ int main () { while (!WindowShouldClose()) { BeginDrawing(); - ClearBackground(BLACK); + ClearBackground(COLOR_BG); + // Grille fond + for(int i=UI_WIDTH; i<1920; i+=100) DrawLine(i, 0, i, 1080, Fade(WHITE, 0.05f)); + for(int i=0; i<1080; i+=100) DrawLine(UI_WIDTH, i, 1920, i, Fade(WHITE, 0.05f)); + DrawMichelsonSchema(&mic); DrawControlPanel(&mic); DrawInterferenceView(&mic, screenViewBounds); diff --git a/michelson b/michelson index a6fcbec..e5b24af 100755 Binary files a/michelson and b/michelson differ