summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--AnimationRender/F_Interpolate.c9
-rw-r--r--AnimationRender/F_Interpolate.h2
-rw-r--r--FrameRender/P_LineSegment.c44
-rw-r--r--FrameRender/P_LineSegment.h17
-rw-r--r--graphics.c92
5 files changed, 119 insertions, 45 deletions
diff --git a/AnimationRender/F_Interpolate.c b/AnimationRender/F_Interpolate.c
index 3cb3b5a..4686adf 100644
--- a/AnimationRender/F_Interpolate.c
+++ b/AnimationRender/F_Interpolate.c
@@ -63,6 +63,15 @@ void Interpolate_Image(Image* value, const Image* start, const Image* end, doubl
fprintf(stderr, "Refusing to interpolate between images!");
}
+void Interpolate_LineSegment(LineSegment* value, const LineSegment* start, const LineSegment* end, double progress) {
+ value->aX = NUM_INTERPOLATE(start->aX, end->aX, progress);
+ value->aY = NUM_INTERPOLATE(start->aY, end->aY, progress);
+ value->bX = NUM_INTERPOLATE(start->bX, end->bX, progress);
+ value->bY = NUM_INTERPOLATE(start->bY, end->bY, progress);
+ value->width = NUM_INTERPOLATE(start->width, end->width, progress);
+ value->color = colorInterpolate(start->color, end->color, progress);
+}
+
void Interpolate_TransformCenter(TransformCenter* value, const TransformCenter* start, const TransformCenter* end, double progress) {
value->centerX = NUM_INTERPOLATE(start->centerX, end->centerX, progress);
value->centerY = NUM_INTERPOLATE(start->centerY, end->centerY, progress);
diff --git a/AnimationRender/F_Interpolate.h b/AnimationRender/F_Interpolate.h
index 2f68c53..90b1eaf 100644
--- a/AnimationRender/F_Interpolate.h
+++ b/AnimationRender/F_Interpolate.h
@@ -6,6 +6,7 @@
#include "../FrameRender/P_Circle.h"
#include "../FrameRender/P_Checker.h"
#include "../FrameRender/P_Image.h"
+#include "../FrameRender/P_LineSegment.h"
#include "../FrameRender/P_TransformCenter.h"
#include "../FrameRender/P_TransformRotate.h"
@@ -24,6 +25,7 @@ void Interpolate_Square(Square* value, const Square* start, const Square* end, d
void Interpolate_Circle(Circle* value, const Circle* start, const Circle* end, double progress);
void Interpolate_Checker(Checker* value, const Checker* start, const Checker* end, double progress);
void Interpolate_Image(Image* value, const Image* start, const Image* end, double progress);
+void Interpolate_LineSegment(LineSegment* value, const LineSegment* start, const LineSegment* end, double progress);
void Interpolate_TransformCenter(TransformCenter* value, const TransformCenter* start, const TransformCenter* end, double progress);
void Interpolate_TransformRotate(TransformRotate* value, const TransformRotate* start, const TransformRotate* end, double progress);
diff --git a/FrameRender/P_LineSegment.c b/FrameRender/P_LineSegment.c
new file mode 100644
index 0000000..f2236ff
--- /dev/null
+++ b/FrameRender/P_LineSegment.c
@@ -0,0 +1,44 @@
+#include "P_LineSegment.h"
+#include "PixelCallback.h"
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+
+void rotatePoint(i32* x, i32* y, double angle) {
+ i32 xR = *x * cos(angle) + *y * sin(angle);
+ i32 yR = - *x * sin(angle) + *y * cos(angle);
+ *x = xR;
+ *y = yR;
+}
+
+void LineSegment_callback(LineSegment* self, struct PixelContext* fc) {
+ /* IDK if this is the most efficient, online results seem
+ * to do more complicated calculations.
+ * Center coordianates around aX,aY
+ * Then unrotate bX,bY and x,y relative to 0,0 (aX,aY),
+ * so that bX,bY lies on the horizontal axis.
+ * Now the line is flat from 0,0 to the "right" (increasing x).
+ */
+ i32 x = fc->x - self->aX, y = fc->y - self->aY;
+ i32 bX = self->bX - self->aX, bY = self->bY - self->aY;
+
+ double phi = atan2(bY, bX);
+ rotatePoint(&y, &x, -phi);
+ rotatePoint(&bY, &bX, -phi);
+
+ if (0 <= x && x <= bX &&
+ -(i32)self->width / 2 <= y && y <= self->width / 2)
+ {
+ ARGB_merge(&fc->pixel, self->color);
+ }
+}
+
+PixelCallback* LineSegment_setup(LineSegment obj) {
+ PixelCallback* pca = malloc(sizeof(struct PixelCallback));
+
+ pca->callback = (PixelCallback_callback)LineSegment_callback;
+ pca->callback_self = malloc(sizeof(obj));
+ memcpy(pca->callback_self, &obj, sizeof(obj));
+
+ return pca;
+}
diff --git a/FrameRender/P_LineSegment.h b/FrameRender/P_LineSegment.h
new file mode 100644
index 0000000..2e52766
--- /dev/null
+++ b/FrameRender/P_LineSegment.h
@@ -0,0 +1,17 @@
+#ifndef P_LINE_SEGMENT
+#define P_LINE_SEGMENT
+
+#include "PixelCallback.h"
+
+typedef struct LineSegment {
+ i32 aX;
+ i32 aY;
+ i32 bX;
+ i32 bY;
+ u32 width;
+ color color;
+} LineSegment;
+
+PixelCallback* LineSegment_setup(LineSegment obj);
+
+#endif /* P_LINE_SEGMENT */
diff --git a/graphics.c b/graphics.c
index d7e5ebd..4b1a470 100644
--- a/graphics.c
+++ b/graphics.c
@@ -11,6 +11,7 @@
#include "FrameRender/P_Checker.h"
#include "FrameRender/P_Circle.h"
#include "FrameRender/P_Image.h"
+#include "FrameRender/P_LineSegment.h"
#include "FrameRender/P_Square.h"
#include "FrameRender/P_TransformCenter.h"
#include "FrameRender/P_TransformRotate.h"
@@ -24,75 +25,77 @@ int
main() {
u32 width = 512;
u32 height = 512;
+ const u32 FPS = 60;
+ u32 frames = FPS * 5;
- FILE* fbclc = fopen("bclc.ppm", "rb");
- RGBImage bclc = ppm_read(fbclc);
- fclose(fbclc);
+ TransformCenter childLeft = { .centerX = width / 4, .centerY = height * 3 / 4, };
+ TransformCenter childRight = { .centerX = width * 3 / 4, .centerY = height * 3 / 4, };
+ LineSegment segmentRight = {
+ .aX = width / 2, .aY = height / 4,
+ .bX = width * 3 / 4, .bY = height * 3 / 4,
+ .width = 10, .color = 0xFFFF00FF,
+ };
+ LineSegment segmentLeft = {
+ .aX = width / 2, .aY = height / 4,
+ .bX = width / 4, .bY = height * 3 / 4,
+ .width = 10, .color = 0xFFFF00FF,
+ };
PixelCallback* callbacks[] = {
- Checker_setup((Checker){
- .squareSize = 64, .colorA = 0xFF000000, .colorB = 0xFFFF00FF,
- }),
- TransformCenter_setup((TransformCenter){
- .centerX = width / 2, .centerY = height / 2,
- }),
- Square_setup((Square){
- .size = 100, .color = 0xFFFFFF00,
- }),
- NULL,
- TransformRotate_setup((TransformRotate){
- .angle = M_PI / 8,
- }),
+ /* Background */
Square_setup((Square){
- .size = 200, .color = 0xFF00FFFF,
+ .size = width, .color = 0xFFF0F0F0,
}),
- NULL,
+ /* Root node */
TransformCenter_setup((TransformCenter){
- .centerX = width * 3/4, .centerY = height / 2,
+ .centerX = width / 2, .centerY = height / 4,
}),
Circle_setup((Circle){
- .radius = 50, .color = 0x80FFFFFF,
+ .radius = 60, .color = 0xFFFF0000,
}),
+ /* Child node */
NULL,
- TransformCenter_setup((TransformCenter){
- .centerX = width / 8, .centerY = height * 3/5,
+ TransformCenter_setup(childRight),
+ Circle_setup((Circle){
+ .radius = 60, .color = 0xFF00FF00,
}),
- Image_setup((Image){
- .img = bclc,
- .scale = 0.2,
+ /* Connecting line */
+ NULL,
+ LineSegment_setup((LineSegment){
+ .aX = width / 2, .aY = height / 4,
+ .bX = width * 3 / 4, .bY = height * 3 / 4,
+ .width = 10, .color = 0xFFFF00FF,
}),
};
u32 sizeCallbacks = sizeof(callbacks) / sizeof(*callbacks);
- TransformCenter img1 = { .centerX = width / 8, .centerY = height * 3/5 },
- img2 = { .centerX = height / 8, .centerY = width / 8 };
-
- TransformRotate r1 = { .angle = M_PI / 8 }, r2 = { .angle = M_PI * 2 };
-
- Circle c1 = { .radius = 50, .color = 0x00FFFFFF, }, c2 = { .radius = 50, .color = 0xFFFFFFFF, };
-
FrameCallback* frameCallbacks[] = {
- Interpolate_setup((Interpolate){
- .startValue = &c1, .endValue = &c2,
- .value = callbacks[8]->callback_self,
- .interpolate = (f_interpolate)Interpolate_Circle,
- }),
FrameRange_setup((FrameRange){
- .startFrame = 25, .endFrame = 125,
+ .startFrame = frames / 3 - FPS, .endFrame = frames / 3,
}),
Interpolate_setup((Interpolate){
- .startValue = &img1, .endValue = &img2,
- .value = callbacks[10]->callback_self,
+ .startValue = &childRight, .endValue = &childLeft,
+ .value = callbacks[4]->callback_self,
.interpolate = (f_interpolate)Interpolate_TransformCenter,
}),
+ Interpolate_setup((Interpolate){
+ .startValue = &segmentRight, .endValue = &segmentLeft,
+ .value = callbacks[7]->callback_self,
+ .interpolate = (f_interpolate)Interpolate_LineSegment,
+ }),
NULL,
FrameRange_setup((FrameRange){
- .startFrame = 0, .endFrame = 50,
+ .startFrame = frames * 2 / 3 - FPS, .endFrame = frames * 2 / 3,
}),
Interpolate_setup((Interpolate){
- .startValue = &r1, .endValue = &r2,
+ .startValue = &childLeft, .endValue = &childRight,
.value = callbacks[4]->callback_self,
- .interpolate = (f_interpolate)Interpolate_TransformRotate,
+ .interpolate = (f_interpolate)Interpolate_TransformCenter,
+ }),
+ Interpolate_setup((Interpolate){
+ .startValue = &segmentLeft, .endValue = &segmentRight,
+ .value = callbacks[7]->callback_self,
+ .interpolate = (f_interpolate)Interpolate_LineSegment,
}),
NULL,
Draw_setup((Draw){
@@ -101,9 +104,8 @@ main() {
};
u32 sizeFrameCallbacks = sizeof(frameCallbacks) / sizeof(*frameCallbacks);
- RenderAnimation(width, height, 150, (const FrameCallback**)frameCallbacks, sizeFrameCallbacks);
+ RenderAnimation(width, height, frames, (const FrameCallback**)frameCallbacks, sizeFrameCallbacks);
- RGBImage_delete(&bclc);
for (u32 i = 0; i < sizeCallbacks; ++i) {
if (callbacks[i] == NULL) continue;
free(callbacks[i]->callback_self);