Add easing functions

This commit is contained in:
2023-12-29 13:30:37 +01:00
parent 7ec5e2122e
commit 4c39e621fe
5 changed files with 291 additions and 0 deletions

View File

@@ -57,6 +57,7 @@ set(BreezeHeaders
breeze/core/logger.h breeze/core/logger.h
breeze/math/vec2i.h breeze/math/vec2i.h
breeze/math/easings.h
breeze/memory/memory.h breeze/memory/memory.h
breeze/memory/stack_alloc.h breeze/memory/stack_alloc.h

View File

@@ -4,6 +4,7 @@
#include "breeze/core/logger.h" #include "breeze/core/logger.h"
#include "breeze/math/vec2i.h" #include "breeze/math/vec2i.h"
#include "breeze/math/easings.h"
#include "breeze/memory/memory.h" #include "breeze/memory/memory.h"
#include "breeze/memory/stack_alloc.h" #include "breeze/memory/stack_alloc.h"

View File

@@ -0,0 +1,227 @@
#ifndef BREEZE_EASINGS_H
#define BREEZE_EASINGS_H
#include <math.h>
// From: https://easings.net/
typedef enum BzEaseType {
BZ_EASE_NONE,
BZ_EASE_IN_SINE,
BZ_EASE_OUT_SINE,
BZ_EASE_INOUT_SINE,
BZ_EASE_IN_QUAD,
BZ_EASE_OUT_QUAD,
BZ_EASE_INOUT_QUAD,
BZ_EASE_IN_CUBIC,
BZ_EASE_OUT_CUBIC,
BZ_EASE_INOUT_CUBIC,
BZ_EASE_IN_QUART,
BZ_EASE_OUT_QUART,
BZ_EASE_INOUT_QUART,
BZ_EASE_IN_QUINT,
BZ_EASE_OUT_QUINT,
BZ_EASE_INOUT_QUINT,
BZ_EASE_IN_EXPO,
BZ_EASE_OUT_EXPO,
BZ_EASE_INOUT_EXPO,
BZ_EASE_IN_CIRC,
BZ_EASE_OUT_CIRC,
BZ_EASE_INOUT_CIRC,
BZ_EASE_IN_BACK,
BZ_EASE_OUT_BACK,
BZ_EASE_INOUT_BACK,
BZ_EASE_IN_ELASTIC,
BZ_EASE_OUT_ELASTIC,
BZ_EASE_INOUT_ELASTIC,
BZ_EASE_IN_BOUNCE,
BZ_EASE_OUT_BOUNCE,
BZ_EASE_INOUT_BOUNCE,
} BzEaseType;
static f32 bzEaseNone(f32 x) {
return x;
}
static f32 bzEaseInSine(f32 x) {
return 1 - cosf((x * M_PI) / 2.0f);
}
static f32 bzEaseOutSine(f32 x) {
return sinf((x * M_PI) / 2.0f);
}
f32 bzEaseInOutSine(f32 x) {
return -(-cosf(M_PI * x) - 1) / 2.0f;
}
static f32 bzEaseInQuad(f32 x) {
return x * x;
}
static f32 bzEaseOutQuad(f32 x) {
return 1 - (1 - x) * (1 - x);
}
static f32 bzEaseInOutQuad(f32 x) {
return x < 0.5f ? 2.0f * x * x : 1 - powf(-2.0f * x + 2, 2) / 2.0f;
}
static f32 bzEaseInCubic(f32 x) {
return x * x * x;
}
static f32 bzEaseOutCubic(f32 x) {
return 1 - powf(1 - x, 3);
}
static f32 bzEaseInOutCubic(f32 x) {
return x < 0.5 ? 4 * x * x * x : 1 - powf(-2.0f * x + 2, 3) / 2.0f;
}
static f32 bzEaseInQuart(f32 x) {
return x * x * x * x;
}
static f32 bzEaseOutQuart(f32 x) {
return 1 - powf(1 - x, 4);
}
static f32 bzEaseInOutQuart(f32 x) {
return x < 0.5 ? 8 * x * x * x * x : 1 - powf(-2 * x + 2, 4) / 2.0f;
}
static f32 bzEaseInQuint(f32 x) {
return x * x * x * x * x;
}
static f32 bzEaseOutQuint(f32 x) {
return 1 - powf(1 - x, 5);
}
static f32 bzEaseInOutQuint(f32 x) {
return x < 0.5 ? 16 * x * x * x * x * x : 1 - powf(-2 * x + 2, 5) / 2.0f;
}
static f32 bzEaseInExpo(f32 x) {
return x == 0 ? 0 : powf(2, 10 * x - 10);
}
static f32 bzEaseOutExpo(f32 x) {
return x == 1 ? 1 : 1 - powf(2, -10 * x);
}
static f32 bzEaseInOutExpo(f32 x) {
if (x == 0) return 0;
if (x == 1) return 1;
return x < 0.5 ? powf(2, 20 * x - 10) / 2.0 : (2 - powf(2, -20 * x + 10)) / 2.0;
}
static f32 bzEaseInCirc(f32 x) {
return 1 - sqrtf(1 - powf(x, 2));
}
static f32 bzEaseOutCirc(f32 x) {
return sqrtf(1 - powf(x - 1, 2));
}
static f32 bzEaseInOutCirc(f32 x) {
return x < 0.5
? (1 - sqrtf(1 - powf(2 * x, 2))) / 2
: (sqrtf(1 - powf(-2 * x + 2, 2)) + 1) / 2;
}
static f32 bzEaseInBack(f32 x) {
const f32 c1 = 1.70158f;
const f32 c3 = c1 + 1;
return (c3 * x * x * x) - (c1 * x * x);
}
static f32 bzEaseOutBack(f32 x) {
const f32 c1 = 1.70158f;
const f32 c3 = c1 + 1;
return 1 + (c3 * powf(x - 1, 3)) + (c1 * powf(x - 1, 2));
}
static f32 bzEaseInOutBack(f32 x) {
const f32 c1 = 1.70158f;
const f32 c2 = c1 * 1.525;
return x < 0.5
? (powf(2 * x, 2) * ((c2 + 1) * 2 * x - c2)) / 2.0f
: (powf(2 * x - 2, 2) * ((c2 + 1) * (x * 2 - 2) + c2) + 2) / 2.0f;
}
static f32 bzEaseInElastic(f32 x) {
const f32 c4 = (2 * M_PI) / 3.0f;
if (x == 0) return 0;
if (x == 1) return 1;
return -powf(2, 10 * x - 10) * sinf((x * 10 - 10.75) * c4);
}
static f32 bzEaseOutElastic(f32 x) {
const f32 c4 = (2 * M_PI) / 3.0f;
if (x == 0) return 0;
if (x == 1) return 1;
return powf(2, -10 * x) * sinf((x * 10 - 0.75) * c4) + 1;
}
static f32 bzEaseInOutElastic(f32 x) {
const f32 c5 = (2 * M_PI) / 4.5f;
if (x == 0) return 0;
if (x == 1) return 1;
return x < 0.5 ?
-(powf(2, 20 * x - 10) * sinf((20 * x - 11.125) * c5)) / 2.0f :
(powf(2, -20 * x + 10) * sinf((20 * x - 11.125) * c5)) / 2.0f + 1;
}
static f32 bzEaseOutBounce(f32 x);
static f32 bzEaseInBounce(f32 x) {
return 1 - bzEaseOutBounce(1 - x);
}
static f32 bzEaseOutBounce(f32 x) {
const f32 n1 = 7.5625;
const f32 d1 = 2.75;
if (x < 1 / d1) {
return n1 * x * x;
} else if (x < 2 / d1) {
return (x -= 1.5f / d1, n1 * x * x + 0.75f);
} else if (x < 2.5 / d1) {
return (x -= 2.25 / d1, n1 * x * x + 0.9375);
} else {
return (x -= 2.625 / d1, n1 * x * x + 0.984375);
}
}
static f32 bzEaseInOutBounce(f32 x) {
return x < 0.5
? (1 - bzEaseOutBounce(1 - 2 * x)) / 2.0f
: (1 + bzEaseOutBounce(2 * x - 1)) / 2.0f;
}
static f32 bzEase(BzEaseType easeType, f32 x) {
switch (easeType) {
case BZ_EASE_NONE: return bzEaseNone(x);
case BZ_EASE_IN_SINE: return bzEaseInSine(x);
case BZ_EASE_OUT_SINE: return bzEaseOutSine(x);
case BZ_EASE_INOUT_SINE: return bzEaseInOutSine(x);
case BZ_EASE_IN_QUAD: return bzEaseInQuad(x);
case BZ_EASE_OUT_QUAD: return bzEaseOutQuad(x);
case BZ_EASE_INOUT_QUAD: return bzEaseInOutQuad(x);
case BZ_EASE_IN_CUBIC: return bzEaseInCubic(x);
case BZ_EASE_OUT_CUBIC: return bzEaseOutCubic(x);
case BZ_EASE_INOUT_CUBIC: return bzEaseInOutCubic(x);
case BZ_EASE_IN_QUART: return bzEaseInQuart(x);
case BZ_EASE_OUT_QUART: return bzEaseOutQuart(x);
case BZ_EASE_INOUT_QUART: return bzEaseInOutQuart(x);
case BZ_EASE_IN_QUINT: return bzEaseInQuint(x);
case BZ_EASE_OUT_QUINT: return bzEaseOutQuint(x);
case BZ_EASE_INOUT_QUINT: return bzEaseInOutQuint(x);
case BZ_EASE_IN_EXPO: return bzEaseInExpo(x);
case BZ_EASE_OUT_EXPO: return bzEaseOutExpo(x);
case BZ_EASE_INOUT_EXPO: return bzEaseInOutExpo(x);
case BZ_EASE_IN_CIRC: return bzEaseInCirc(x);
case BZ_EASE_OUT_CIRC: return bzEaseOutCirc(x);
case BZ_EASE_INOUT_CIRC: return bzEaseInOutCirc(x);
case BZ_EASE_IN_BACK: return bzEaseInBack(x);
case BZ_EASE_OUT_BACK: return bzEaseOutBack(x);
case BZ_EASE_INOUT_BACK: return bzEaseInOutBack(x);
case BZ_EASE_IN_ELASTIC: return bzEaseInElastic(x);
case BZ_EASE_OUT_ELASTIC: return bzEaseOutElastic(x);
case BZ_EASE_INOUT_ELASTIC: return bzEaseInOutElastic(x);
case BZ_EASE_IN_BOUNCE: return bzEaseInBounce(x);
case BZ_EASE_OUT_BOUNCE: return bzEaseOutBounce(x);
case BZ_EASE_INOUT_BOUNCE: return bzEaseInOutBounce(x);
}
}
#endif //BREEZE_EASINGS_H

View File

@@ -22,3 +22,6 @@ target_link_libraries(pan_test LINK_PRIVATE Breeze)
add_executable(ui_test ui_test.c) add_executable(ui_test ui_test.c)
target_link_libraries(ui_test LINK_PRIVATE Breeze) target_link_libraries(ui_test LINK_PRIVATE Breeze)
add_executable(ease_test ease_test.c)
target_link_libraries(ease_test LINK_PRIVATE Breeze)

59
engine/tests/ease_test.c Normal file
View File

@@ -0,0 +1,59 @@
#define BZ_ENTRYPOINT
#include <breeze.h>
#include <raylib.h>
#include <rlImGui.h>
bool init(int *game) {
rlImGuiSetup(true);
return true;
}
void render(float dt, int *game) {
static f32 x = 0;
x += dt * 2;
//f32 eased = bzEase(BZ_EASE_INOUT_SINE, x);
f32 eased = bzEase(BZ_EASE_OUT_ELASTIC, x);
Rectangle rect = {
500, 500, 200, 400
};
Vector2 origin = {rect.width * 0.5f, rect.height};
BeginDrawing();
ClearBackground(WHITE);
f32 rotation = 45 * (1 - eased);
DrawRectanglePro(rect, origin, rotation, RED);
if (IsKeyReleased(KEY_SPACE)) {
x = 0.0f;
}
rlImGuiBegin();
igBegin("Easing", NULL, 0);
igText("x: %.2f", x);
igText("eased: %.2f", eased);
igText("rotation: %.2f", rotation);
if (igSmallButton("Reset")) {
x = 0.0f;
}
igEnd();
rlImGuiEnd();
EndDrawing();
}
bool bzMain(BzAppDesc *appDesc, int argc, const char **argv) {
appDesc->init = (BzAppInitFunc) init;
appDesc->render = (BzAppRenderFunc) render;
return true;
}