diff options
| author | Syndamia <kamen@syndamia.com> | 2026-03-28 20:33:03 +0200 |
|---|---|---|
| committer | Syndamia <kamen@syndamia.com> | 2026-03-28 20:33:03 +0200 |
| commit | d31239eeeac4ea595b1d1e7063ab5d762809fb02 (patch) | |
| tree | aa0d5f426a2dc439ad863b9e3ec017c5776f528e | |
| parent | 56099072165578b505a6c81e187cf392b9bd5a2e (diff) | |
| download | ppm_graphics-d31239eeeac4ea595b1d1e7063ab5d762809fb02.tar ppm_graphics-d31239eeeac4ea595b1d1e7063ab5d762809fb02.tar.gz ppm_graphics-d31239eeeac4ea595b1d1e7063ab5d762809fb02.zip | |
feat!: Complete rewrite
This new scheme will be much simpler
| -rw-r--r-- | Animation.c | 118 | ||||
| -rw-r--r-- | Animation.h | 44 | ||||
| -rw-r--r-- | AnimationInterpolate.c | 78 | ||||
| -rw-r--r-- | AnimationInterpolate.h | 22 | ||||
| -rw-r--r-- | AnimationMove.c | 34 | ||||
| -rw-r--r-- | AnimationMove.h | 31 | ||||
| -rw-r--r-- | AnimationObject.c | 78 | ||||
| -rw-r--r-- | AnimationObject.h | 56 | ||||
| -rw-r--r-- | FrameRender/FrameRender.c | 25 | ||||
| -rw-r--r-- | FrameRender/FrameRender.h | 10 | ||||
| -rw-r--r-- | FrameRender/P_Square.c | 22 | ||||
| -rw-r--r-- | FrameRender/P_Square.h | 14 | ||||
| -rw-r--r-- | FrameRender/P_TransformCenter.c | 19 | ||||
| -rw-r--r-- | FrameRender/P_TransformCenter.h | 14 | ||||
| -rw-r--r-- | FrameRender/PixelCallback.h | 20 | ||||
| -rw-r--r-- | global.h | 2 | ||||
| -rw-r--r-- | graphics.c | 190 |
17 files changed, 155 insertions, 622 deletions
diff --git a/Animation.c b/Animation.c deleted file mode 100644 index 2dc6380..0000000 --- a/Animation.c +++ /dev/null @@ -1,118 +0,0 @@ -#include "Animation.h" -#include <stdlib.h> - -struct AnimationEventNode { - AnimationEventNode* next; - - u32 startFrame; - u32 endFrame; - PixelRenderer renderCallback; - void* privateData; -}; - -AnimationEventNode* -AnimationEventNode_new(u32 startFrame, u32 endFrame, PixelRenderer renderCallback, void* privateData) { - AnimationEventNode* aen = (AnimationEventNode*)malloc(sizeof(AnimationEventNode)); - aen->next = NULL; - aen->startFrame = startFrame; - aen->endFrame = endFrame; - aen->renderCallback = renderCallback; - aen->privateData = privateData; - - return aen; -} - -Animation -Animation_new(u32 width, u32 height, u32 frameCount) { - return (Animation){ - .width = width, - .height = height, - .frameCount = frameCount, - .duplicateFrames = 0, - .frameBuffer = RGBImage_new(width, height), - .events = NULL, - }; -} - -void -Animation_free(Animation anim) { - RGBImage_free(anim.frameBuffer); - while (anim.events != NULL) { - AnimationEventNode* toFree = anim.events; - anim.events = anim.events->next; - free(toFree); - } -} - -void -Animation_delete(Animation* anim) { - Animation_free(*anim); - anim->width = anim->height = anim->frameCount = 0; - RGBImage_delete(&anim->frameBuffer); -} - -void -Animation_pushEvent(Animation* anim, u32 startFrame, u32 endFrame, PixelRenderer renderer, void* privateData) { - if (anim->events == NULL) { - anim->events = AnimationEventNode_new(startFrame, endFrame, renderer, privateData); - return; - } - - AnimationEventNode* prevNode = NULL, *currNode = anim->events; - while (currNode != NULL) { - if (startFrame < currNode->startFrame) { - prevNode->next = AnimationEventNode_new(startFrame, endFrame, renderer, privateData); - prevNode->next->next = currNode; - return; - } - - prevNode = currNode; - currNode = currNode->next; - } - - prevNode->next = AnimationEventNode_new(startFrame, endFrame, renderer, privateData); -} - -void -Animation_render(Animation* anim) { - for (u32 currFrame = 0; currFrame < anim->frameCount; ++currFrame) { - if (anim->events != NULL) - for (i32 r = 0; r < anim->frameBuffer.width; ++r) - for (i32 c = 0; c < anim->frameBuffer.height; ++c) { - for (AnimationEventNode* aen = anim->events; aen != NULL && aen->startFrame <= currFrame; aen = aen->next) { - ARGB* pixel = RGBImage_at(anim->frameBuffer, r, c); - ARGB newPixel = aen->renderCallback(anim, (PixelRendererParams){ - .frame = { - .current = currFrame, - .start = aen->startFrame, - .end = aen->endFrame, - }, - .pixel = *pixel, - .row = r, .col = c, - .priv = aen->privateData, - }); - ARGB_merge(pixel, newPixel); - } - - AnimationEventNode* prevNode = NULL, *currNode = anim->events; - while (currNode != NULL && currNode->startFrame <= currFrame) { - if (currNode->endFrame <= currFrame) { - if (prevNode != NULL) - prevNode->next = currNode->next; - else - anim->events = NULL; - free(currNode); - } - else { - prevNode = currNode; - currNode = currNode->next; - } - } - } - - ppm6_write(stdout, anim->frameBuffer); - - for (u32 duplicates = 0; duplicates < anim->duplicateFrames; ++duplicates) - ppm6_write(stdout, anim->frameBuffer); - } -} diff --git a/Animation.h b/Animation.h deleted file mode 100644 index 6cebdb0..0000000 --- a/Animation.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef _ANIMATION -#define _ANIMATION - -#include "RGBImage.h" - -struct AnimationEventNode; -typedef struct AnimationEventNode AnimationEventNode; - -typedef struct Animation { - u32 width; - u32 height; - u32 frameCount; - u32 duplicateFrames; - - RGBImage frameBuffer; - AnimationEventNode* events; -} Animation; - -typedef struct PixelRendererParams { - struct Frames { - u32 current; - u32 start; - u32 end; - } frame; - - ARGB pixel; - - i32 row; - i32 col; - - void* priv; -} PixelRendererParams; - -typedef ARGB (*PixelRenderer)(const Animation* anim, PixelRendererParams params); - -AnimationEventNode* AnimationEventNode_new(u32 startFrame, u32 endFrame, PixelRenderer renderCallback, void* privateData); -Animation Animation_new(u32 width, u32 height, u32 frameCount); -void Animation_free(Animation anim); -void Animation_delete(Animation* anim); - -void Animation_pushEvent(Animation* anim, u32 startFrame, u32 endFrame, PixelRenderer renderer, void* privateData); -void Animation_render(Animation* anim); - -#endif /* _ANIMATION */ diff --git a/AnimationInterpolate.c b/AnimationInterpolate.c deleted file mode 100644 index a84b5a2..0000000 --- a/AnimationInterpolate.c +++ /dev/null @@ -1,78 +0,0 @@ -#include "AnimationInterpolate.h" -#include "AnimationObject.h" -#include "AnimationMove.h" -#include <string.h> - -#define NUM_INTERPOLATE(a, b, perc) (a * (1.0 - (perc)) + b * (perc)) - -color -colorInterpolate(color ina, color inb, double percentage) { - ARGB a, b; - ARGB_set(&a, ina); - ARGB_set(&b, inb); - - a.a = NUM_INTERPOLATE(a.a, b.a, percentage); - a.r = NUM_INTERPOLATE(a.r, b.r, percentage); - a.g = NUM_INTERPOLATE(a.g, b.g, percentage); - a.b = NUM_INTERPOLATE(a.b, b.b, percentage); - - return a.a << 24 | a.r << 16 | a.g << 8 | a.b; -} - -ARGB -A_Interpolate(const Animation* anim, PixelRendererParams a) { - struct A_Interpolate in = *(struct A_Interpolate*)a.priv; - - if (in.interpolate == NULL) { - fprintf(stderr, "Interpolation function cannot be NULL!\n"); - ARGB_set(&a.pixel, 0xFFFF00FF); - return a.pixel; - } - - if (a.frame.current == a.frame.start) { - memcpy(in.initialValueTemp, in.value, in.initialValueTempSize); - } - - double perc = (double)(a.frame.current - a.frame.start) / (a.frame.end - a.frame.start); - if (perc < 0.0) perc = 0.0; - if (perc > 1.0) perc = 1.0; - - in.interpolate(in.value, in.initialValueTemp, in.goalValue, perc); - - return a.pixel; -} - -void -AO_LineInterpolate(void* valueLine, const void* initialLine, const void* finalLine, double percentage) { - struct AO_Line* value = valueLine; - const struct AO_Line* initial = initialLine, *final = finalLine; - - value->a = NUM_INTERPOLATE(initial->a, final->a, percentage); - value->b = NUM_INTERPOLATE(initial->b, final->b, percentage); - value->c = NUM_INTERPOLATE(initial->c, final->c, percentage); - value->width = NUM_INTERPOLATE(initial->width, final->width, percentage); - value->color = colorInterpolate(initial->color, final->color, percentage); -} - -void -AM_LinearInterpolate(void* valueIn, const void* initialIn, const void* finalIn, double percentage) { - struct AM_Linear* value = valueIn; - const struct AM_Linear* initial = initialIn, *final = finalIn; - - value->startRow = NUM_INTERPOLATE(initial->startRow, final->startRow, percentage); - value->startCol = NUM_INTERPOLATE(initial->startCol, final->startCol, percentage); - value->dRow = NUM_INTERPOLATE(initial->dRow, final->dRow, percentage); - value->dCol = NUM_INTERPOLATE(initial->dCol, final->dCol, percentage); - value->wrapCoordinates = NUM_INTERPOLATE(initial->wrapCoordinates, final->wrapCoordinates, percentage); -} - -void -AM_SpinInterpolate(void* valueIn, const void* initialIn, const void* finalIn, double percentage) { - struct AM_Spin* value = valueIn; - const struct AM_Spin* initial = initialIn, *final = finalIn; - - value->theta = NUM_INTERPOLATE(initial->theta, final->theta, percentage); - value->dTheta = NUM_INTERPOLATE(initial->dTheta, final->dTheta, percentage); - value->centerRow = NUM_INTERPOLATE(initial->centerRow, final->centerRow, percentage); - value->centerCol = NUM_INTERPOLATE(initial->centerCol, final->centerCol, percentage); -} diff --git a/AnimationInterpolate.h b/AnimationInterpolate.h deleted file mode 100644 index 18ae841..0000000 --- a/AnimationInterpolate.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef _ANIMATION_INTERPOLATE -#define _ANIMATION_INTERPOLATE - -#include "Animation.h" - -struct A_Interpolate { - void* initialValueTemp; - size_t initialValueTempSize; - - void* value; - void* goalValue; - void (*interpolate)(void* value, const void* initialState, const void* finalState, double percentage); -}; - -ARGB A_Interpolate(const Animation* anim, PixelRendererParams params); - -void AO_LineInterpolate(void* valueLine, const void* initialLine, const void* finalLine, double percentage); - -void AM_LinearInterpolate(void* valueLinear, const void* initialLinear, const void* finalLinear, double percentage); -void AM_SpinInterpolate(void* valueSpin, const void* initialSpin, const void* finalSpin, double percentage); - -#endif /* _ANIMATION_INTERPOLATE */ diff --git a/AnimationMove.c b/AnimationMove.c deleted file mode 100644 index 7ac52f9..0000000 --- a/AnimationMove.c +++ /dev/null @@ -1,34 +0,0 @@ -#include "AnimationMove.h" -#include <math.h> - -ARGB -AM_Linear(const Animation* anim, PixelRendererParams a) { - struct AM_Linear ml = *(struct AM_Linear*)a.priv; - - a.row = (a.row - ml.startRow - (i32)(a.frame.current * ml.dRow)); - a.col = (a.col - ml.startCol - (i32)(a.frame.current * ml.dCol)); - - if (ml.wrapCoordinates == true) { - a.row %= anim->width; - a.col %= anim->height; - } - - a.priv = ml.priv; - return ml.callback(anim, a); -} - -ARGB -AM_Spin(const Animation* anim, PixelRendererParams a) { - struct AM_Spin ms = *(struct AM_Spin*)a.priv; - - double radius = sqrt(a.row * a.row + a.col * a.col); - double phi = atan2(a.col, a.row); - - phi += ms.theta + ms.dTheta * a.frame.current; - - a.row = (ms.centerRow + (i32)(radius * cos(phi))); - a.col = (ms.centerCol + (i32)(radius * sin(phi))); - - a.priv = ms.priv; - return ms.callback(anim, a); -} diff --git a/AnimationMove.h b/AnimationMove.h deleted file mode 100644 index 48a3b92..0000000 --- a/AnimationMove.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef _ANIMATION_MOVE -#define _ANIMATION_MOVE - -#include "Animation.h" - -struct AM_Linear { - PixelRenderer callback; - void* priv; - - i32 startRow; - i32 startCol; - float dRow; - float dCol; - bool wrapCoordinates; -}; - -ARGB AM_Linear(const Animation* anim, PixelRendererParams params); - -struct AM_Spin { - PixelRenderer callback; - void* priv; - - float theta; - float dTheta; - i32 centerRow; - i32 centerCol; -}; - -ARGB AM_Spin(const Animation* anim, PixelRendererParams params); - -#endif /* _ANIMATION_MOVE */ diff --git a/AnimationObject.c b/AnimationObject.c deleted file mode 100644 index 63594ce..0000000 --- a/AnimationObject.c +++ /dev/null @@ -1,78 +0,0 @@ -#include "AnimationObject.h" -#include <math.h> -#include <stdlib.h> - -ARGB -AO_CheckerPattern(const Animation* anim, PixelRendererParams a) { - struct AO_CheckerPattern chp = *(struct AO_CheckerPattern*)a.priv; - - a.row /= chp.squareSize; - a.col /= chp.squareSize; - - if ((a.row + a.col) % 2 == 0) { - ARGB_set(&a.pixel, 0xFF000000); - } - else { - ARGB_set(&a.pixel, 0xFFFF00FF); - } - - return a.pixel; -} - -ARGB -AO_Square(const Animation* anim, PixelRendererParams a) { - struct AO_Square* set = (struct AO_Square*)a.priv; - - if (0 <= a.row && a.row <= set->width && 0 <= a.col && a.col <= set->height) { - ARGB_set(&a.pixel, set->color); - } - - return a.pixel; -} - -ARGB -AO_Circle(const Animation* anim, PixelRendererParams a) { - struct AO_Circle* cir = (struct AO_Circle*)a.priv; - - if (a.row * a.row + a.col * a.col < cir->radius * cir->radius) { - ARGB_set(&a.pixel, cir->color); - } - - return a.pixel; -} - -ARGB -AO_Image(const Animation* anim, PixelRendererParams a) { - struct AO_Image img = *(struct AO_Image*)a.priv; - - if (img.noRepeat == true && - (a.col < 0 || img.img.width * img.zoom <= a.col || - a.row < 0 || img.img.height * img.zoom <= a.row)) - { - return a.pixel; - } - - return *RGBImage_at(*(RGBImage*)a.priv, a.row / img.zoom, a.col / img.zoom); -} - -ARGB -AO_Line(const Animation* anim, PixelRendererParams a) { - struct AO_Line l = *(struct AO_Line*)a.priv; - - if (fabs(l.a * a.col + l.b * a.row + l.c) / sqrt(l.a * l.a + l.b * l.b) < l.width) { - ARGB_set(&a.pixel, l.color); - } - - return a.pixel; -} - -ARGB -AO_HorSegment(const Animation* anim, PixelRendererParams a) { - struct AO_HorSegment hs = *(struct AO_HorSegment*)a.priv; - - if (abs(a.row) <= hs.width && hs.left <= a.col && a.col <= hs.right) { - ARGB_set(&a.pixel, hs.color); - } - - return a.pixel; -} diff --git a/AnimationObject.h b/AnimationObject.h deleted file mode 100644 index ef8c3a3..0000000 --- a/AnimationObject.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef _ANIMATION_OBJECT -#define _ANIMATION_OBJECT - -#include "Animation.h" - -struct AO_CheckerPattern { - u32 squareSize; - color colorA; - color colorB; -}; - -ARGB AO_CheckerPattern(const Animation* anim, PixelRendererParams params); - -struct AO_Square { - u32 width; - u32 height; - color color; -}; - -ARGB AO_Square(const Animation* anim, PixelRendererParams params); - -struct AO_Circle { - double radius; - color color; -}; - -ARGB AO_Circle(const Animation* anim, PixelRendererParams params); - -struct AO_Image { - RGBImage img; - double zoom; - bool noRepeat; -}; - -ARGB AO_Image(const Animation* anim, PixelRendererParams params); - -struct AO_Line { - double a; - double b; - double c; - double width; - color color; -}; - -ARGB AO_Line(const Animation* anim, PixelRendererParams params); - -struct AO_HorSegment { - i32 left; - i32 right; - double width; - color color; -}; - -ARGB AO_HorSegment(const Animation* anim, PixelRendererParams params); - -#endif /* _ANIMATION_OBJECT */ diff --git a/FrameRender/FrameRender.c b/FrameRender/FrameRender.c new file mode 100644 index 0000000..bf148bd --- /dev/null +++ b/FrameRender/FrameRender.c @@ -0,0 +1,25 @@ +#include "FrameRender.h" +#include <string.h> + +void RenderFrame(RGBImage buffer, const PixelCallback** callbacks, usize sizeCallbacks) { + struct PixelContext pc; + for (u32 x = 0; x < buffer.width; ++x) { + for (u32 y = 0; y < buffer.height; ++y) { + pc.x = x; + pc.y = y; + pc.pixel.a = pc.pixel.r = pc.pixel.g = pc.pixel.b = 0; + + for (usize i = 0; i < sizeCallbacks; ++i) { + // Soft context reset + if (callbacks[i] == NULL) { + pc.x = x; + pc.y = y; + } + else + callbacks[i]->callback(callbacks[i]->callback_self, &pc); + } + + memcpy(RGBImage_at(buffer, y, x), &pc.pixel, sizeof(pc.pixel)); + } + } +} diff --git a/FrameRender/FrameRender.h b/FrameRender/FrameRender.h new file mode 100644 index 0000000..09037cb --- /dev/null +++ b/FrameRender/FrameRender.h @@ -0,0 +1,10 @@ +#ifndef _FRAME_RENDER +#define _FRAME_RENDER + +#include "../global.h" +#include "../RGBImage.h" +#include "PixelCallback.h" + +void RenderFrame(RGBImage buffer, const PixelCallback** callbacks, usize sizeCallbacks); + +#endif /* _FRAME_RENDER */ diff --git a/FrameRender/P_Square.c b/FrameRender/P_Square.c new file mode 100644 index 0000000..7865370 --- /dev/null +++ b/FrameRender/P_Square.c @@ -0,0 +1,22 @@ +#include "P_Square.h" +#include "PixelCallback.h" +#include <stdlib.h> +#include <string.h> + +void Square_callback(Square* self, struct PixelContext* fc) { + if (0 <= fc->x && fc->x <= self->width && + 0 <= fc->y && fc->y <= self->height) + { + ARGB_set(&fc->pixel, self->color); + } +} + +PixelCallback* Square_setup(Square obj) { + PixelCallback* pca = malloc(sizeof(struct PixelCallback)); + + pca->callback = (PixelCallback_callback)Square_callback; + pca->callback_self = malloc(sizeof(obj)); + memcpy(pca->callback_self, &obj, sizeof(obj)); + + return pca; +} diff --git a/FrameRender/P_Square.h b/FrameRender/P_Square.h new file mode 100644 index 0000000..1cfbc45 --- /dev/null +++ b/FrameRender/P_Square.h @@ -0,0 +1,14 @@ +#ifndef P_SQUARE +#define P_SQUARE + +#include "PixelCallback.h" + +typedef struct Square { + u32 width; + u32 height; + color color; +} Square; + +PixelCallback* Square_setup(Square obj); + +#endif /* P_SQUARE */ diff --git a/FrameRender/P_TransformCenter.c b/FrameRender/P_TransformCenter.c new file mode 100644 index 0000000..5388437 --- /dev/null +++ b/FrameRender/P_TransformCenter.c @@ -0,0 +1,19 @@ +#include "P_TransformCenter.h" +#include "PixelCallback.h" +#include <stdlib.h> +#include <string.h> + +void TransformCenter_callback(TransformCenter* self, struct PixelContext* pc) { + pc->x -= self->centerX; + pc->y -= self->centerY; +} + +PixelCallback* TransformCenter_setup(TransformCenter obj) { + PixelCallback* pca = malloc(sizeof(struct PixelCallback)); + + pca->callback = (PixelCallback_callback)TransformCenter_callback; + pca->callback_self = malloc(sizeof(obj)); + memcpy(pca->callback_self, &obj, sizeof(obj)); + + return pca; +} diff --git a/FrameRender/P_TransformCenter.h b/FrameRender/P_TransformCenter.h new file mode 100644 index 0000000..ab75c32 --- /dev/null +++ b/FrameRender/P_TransformCenter.h @@ -0,0 +1,14 @@ +#ifndef P_TRANSFORMCENTER +#define P_TRANSFORMCENTER + +#include "PixelCallback.h" +#include "../global.h" + +typedef struct TransformCenter { + i32 centerX; + i32 centerY; +} TransformCenter; + +PixelCallback* TransformCenter_setup(TransformCenter obj); + +#endif /* P_TRANSFORMCENTER */ diff --git a/FrameRender/PixelCallback.h b/FrameRender/PixelCallback.h new file mode 100644 index 0000000..b0aee1f --- /dev/null +++ b/FrameRender/PixelCallback.h @@ -0,0 +1,20 @@ +#ifndef _PIXEL_CALLBACK +#define _PIXEL_CALLBACK + +#include "../global.h" +#include "../RGBImage.h" + +struct PixelContext { + i32 x; + i32 y; + ARGB pixel; +}; + +typedef void (*PixelCallback_callback)(void* self, struct PixelContext* pc); + +typedef struct PixelCallback { + PixelCallback_callback callback; + void* callback_self; +} PixelCallback; + +#endif /* _PIXEL_CALLBACK */ @@ -9,6 +9,6 @@ typedef uint8_t bool; typedef int32_t i32; typedef uint32_t u32; - +typedef uint32_t usize; #endif /* _GLOBAL */ @@ -2,169 +2,39 @@ * gcc -std=c99 *.c -lm && ./a.out | ffmpeg -r 30 -i - output.mp4 */ -#include "Animation.h" -#include "AnimationObject.h" -#include "AnimationMove.h" -#include "AnimationInterpolate.h" -#include <math.h> - -double -pointDistance(i32 rowA, i32 colA, i32 rowB, i32 colB) { - return sqrt(pow(rowA - rowB, 2) + pow(colA - colB, 2)); -} - -void -HorSegmentByPoints( - i32 rowA, i32 colA, i32 rowB, i32 colB, - struct AO_HorSegment* segment, - struct AM_Spin* rotate, - struct AM_Linear* translate) -{ - segment->left = 0; - segment->right = pointDistance(rowA, colA, rowB, colB); - - rotate->theta = atan2(rowB - rowA, colB - colA); - - translate->startRow = rowA; - translate->startCol = colA; - - rotate->callback = AO_HorSegment; - rotate->priv = segment; - translate->callback = AM_Spin; - translate->priv = rotate; -} +#include "FrameRender/FrameRender.h" +#include "FrameRender/P_Square.h" +#include "FrameRender/P_TransformCenter.h" +#include "RGBImage.h" +#include <stdlib.h> int main() { - const u32 FPS = 60; - Animation anim = Animation_new(512, 512, FPS * 5); - - struct AO_Square background = { - .width = anim.width, .height = anim.height, - .color = 0xFFF0F0F0, - }; - Animation_pushEvent(&anim, 0, anim.frameCount, AO_Square, &background); - - /* Root node */ - struct AO_Circle rootNode_ = { - .radius = 60, .color = 0xFFFF0000, - }; - struct AM_Linear rootNode_linear = { - .callback = AO_Circle, .priv = &rootNode_, - - .startRow = anim.height / 4, .startCol = anim.width / 2, - }; - - struct AM_Linear rootNode = rootNode_linear; - - /* Child node */ - struct AO_Circle childNode_ = { - .radius = 60, .color = 0xFF00FF00, - }; - - struct AM_Linear childNode_left = { - .callback = AO_Circle, .priv = &childNode_, - - .startRow = anim.height * 3 / 4, .startCol = anim.width / 4, - }; - struct AM_Linear childNode_right = { - .callback = AO_Circle, .priv = &childNode_, - - .startRow = anim.height * 3 / 4, .startCol = anim.width * 3 / 4, - }; - - struct AM_Linear childNode = childNode_right; - - /* Root Node --- Child Node */ - struct AO_HorSegment link_ = { - .color = 0xFFFF00FF, .width = 10, - }; - - struct AM_Spin link_spin_left = {}; - struct AM_Linear link_translate_left = {}; - HorSegmentByPoints( - rootNode_linear.startRow, rootNode_linear.startCol, - childNode_left.startRow, childNode_left.startCol, - &link_, &link_spin_left, &link_translate_left); - - struct AM_Spin link_spin_right = {}; - struct AM_Linear link_translate_right = {}; - HorSegmentByPoints( - rootNode_linear.startRow, rootNode_linear.startCol, - childNode_right.startRow, childNode_right.startCol, - &link_, &link_spin_right, &link_translate_right); - - struct AM_Spin link_spin = link_spin_right; - struct AM_Linear link_translate = link_translate_right; - link_translate.priv = &link_spin; - - Animation_pushEvent(&anim, 0, anim.frameCount, AM_Linear, &link_translate); - Animation_pushEvent(&anim, 0, anim.frameCount, AM_Linear, &rootNode); - Animation_pushEvent(&anim, 0, anim.frameCount, AM_Linear, &childNode); - - /* Movement */ - - struct AM_Linear temp1; - struct A_Interpolate childNode_moveToLeft = { - .initialValueTemp = &temp1, .initialValueTempSize = sizeof(temp1), - - .interpolate = AM_LinearInterpolate, - .value = &childNode, .goalValue = &childNode_left, - }; - struct AM_Spin temp11; - struct A_Interpolate segment_spin_moveToLeft = { - .initialValueTemp = &temp11, .initialValueTempSize = sizeof(temp11), - - .interpolate = AM_SpinInterpolate, - .value = &link_spin, .goalValue = &link_spin_left, - }; - struct AM_Linear temp12; - struct A_Interpolate segment_translate_moveToLeft = { - .initialValueTemp = &temp12, .initialValueTempSize = sizeof(temp12), - - .interpolate = AM_LinearInterpolate, - .value = &link_translate, .goalValue = &link_translate_left, - }; - - struct AM_Linear temp2; - struct A_Interpolate childNode_moveToRight = { - .initialValueTemp = &temp2, .initialValueTempSize = sizeof(temp2), - - .interpolate = AM_LinearInterpolate, - .value = &childNode, .goalValue = &childNode_right, - }; - struct AM_Spin temp21; - struct A_Interpolate segment_spin_moveToRight = { - .initialValueTemp = &temp21, .initialValueTempSize = sizeof(temp21), - - .interpolate = AM_SpinInterpolate, - .value = &link_spin, .goalValue = &link_spin_right, - }; - struct AM_Linear temp22; - struct A_Interpolate segment_translate_moveToRight = { - .initialValueTemp = &temp22, .initialValueTempSize = sizeof(temp22), - - .interpolate = AM_LinearInterpolate, - .value = &link_translate, .goalValue = &link_translate_right, - }; - - /* Move child node from right to left */ - - u32 start = anim.frameCount / 3 - FPS, end = anim.frameCount / 3; - Animation_pushEvent(&anim, start, end, A_Interpolate, &childNode_moveToLeft); - Animation_pushEvent(&anim, start, end, A_Interpolate, &segment_spin_moveToLeft); - Animation_pushEvent(&anim, start, end, A_Interpolate, &segment_translate_moveToLeft); - - /* Move child node from left to right */ - - start = anim.frameCount * 2 / 3 - FPS, end = anim.frameCount * 2 / 3; - Animation_pushEvent(&anim, start, end, A_Interpolate, &childNode_moveToRight); - Animation_pushEvent(&anim, start, end, A_Interpolate, &segment_spin_moveToRight); - Animation_pushEvent(&anim, start, end, A_Interpolate, &segment_translate_moveToRight); - - Animation_render(&anim); - - Animation_delete(&anim); + RGBImage frame = RGBImage_new(512, 512); + + PixelCallback* callbacks[] = { + TransformCenter_setup((TransformCenter){ + .centerX = frame.width / 2, .centerY = frame.width / 2, + }), + Square_setup((Square){ + .width = 100, .height = 100, .color = 0xFFFF0000, + }), + NULL, + Square_setup((Square){ + .width = 200, .height = 200, .color = 0xFF00FFFF, + }), + }; + u32 sizeCallbacks = sizeof(callbacks) / sizeof(*callbacks); + + RenderFrame(frame, (const PixelCallback**)callbacks, sizeCallbacks); + ppm6_write(stdout, frame); + + RGBImage_delete(&frame); + for (u32 i = 0; i < sizeCallbacks; ++i) { + if (callbacks[i] == NULL) continue; + free(callbacks[i]->callback_self); + free(callbacks[i]); + } return 0; } |
