summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpacien2017-12-26 18:16:55 +0100
committerpacien2017-12-26 18:16:55 +0100
commit2f74af6a1069b9d662676e3d2cbbc671a67574b5 (patch)
treea6fb231ea2fe8ac4e836ee5ce384f41e059aca12
parent45d01bc6d74ac1982c974f1b891b0ad96b878f3a (diff)
downloadmorpher-2f74af6a1069b9d662676e3d2cbbc671a67574b5.tar.gz
Implement morphing functions and adapt blender
Signed-off-by: pacien <pacien.trangirard@pacien.net>
-rw-r--r--include/blender/blender.h2
-rw-r--r--include/morpher/morphing.h58
-rw-r--r--src/blender/blender.c5
-rw-r--r--src/morpher/morphing.c44
-rw-r--r--test/blender/blender.c8
5 files changed, 109 insertions, 8 deletions
diff --git a/include/blender/blender.h b/include/blender/blender.h
index 8e89208..26ff802 100644
--- a/include/blender/blender.h
+++ b/include/blender/blender.h
@@ -8,7 +8,7 @@
8 8
9#include "common/time.h" 9#include "common/time.h"
10#include "blender/canvas.h" 10#include "blender/canvas.h"
11#include "morpher/morpher.h" 11#include "morpher/morphing.h"
12 12
13/** 13/**
14 * Function: blender_blend_canvas 14 * Function: blender_blend_canvas
diff --git a/include/morpher/morphing.h b/include/morpher/morphing.h
new file mode 100644
index 0000000..028cd87
--- /dev/null
+++ b/include/morpher/morphing.h
@@ -0,0 +1,58 @@
1#ifndef UPEM_MORPHING_MORPHING
2#define UPEM_MORPHING_MORPHING
3
4/**
5 * File: morphing.h
6 * Coordinate mapping for morphing transforms.
7 */
8
9#include "common/geom.h"
10#include "common/time.h"
11#include "morpher/trianglemap.h"
12
13/**
14 * Struct: Morphing
15 * Represents an abstract coordinate transform from a source to a destination coordinate matrix,
16 * constrained by a given set of points.
17 *
18 * Fields:
19 * dim - dimension in pixels
20 * *first - the first triangle in the linked list
21 * *center - the center triangle
22 */
23typedef struct {
24 CartesianVector dim;
25 TriangleMap *first, *center;
26} Morphing;
27
28/**
29 * Function: morphing_init
30 * Initialises a morphing.
31 *
32 * Parameters:
33 * width - coordinate matrix width in pixels
34 * height - coordinate matrix height in pixels
35 */
36Morphing *morphing_create(IntVector width, IntVector height);
37
38/**
39 * Function: morphing_free
40 * Frees any resources allocated to a morphing.
41 *
42 * Parameters:
43 * *m - pointer to the morphing to destroy
44 */
45void morphing_destroy(Morphing *m);
46
47/**
48 * Function: morphing_add_constraint
49 * Adds a constraint point to a morphing.
50 *
51 * Parameters:
52 * *m - pointer to the morphing to alter
53 * origin - constraint point coordinates on the origin matrix
54 * destination - constraint point coordinates on the target matrix
55 */
56void morphing_add_constraint(Morphing *m, CartesianVector origin, CartesianVector destination);
57
58#endif
diff --git a/src/blender/blender.c b/src/blender/blender.c
index 99abedd..08cafa4 100644
--- a/src/blender/blender.c
+++ b/src/blender/blender.c
@@ -1,7 +1,6 @@
1#include "blender/blender.h" 1#include "blender/blender.h"
2#include <assert.h> 2#include <assert.h>
3#include <math.h> 3#include <math.h>
4#include "morpher/morpher.h"
5 4
6static inline ColorComponent blend_components(ColorComponent origin, ColorComponent target, TimeVector frame) { 5static inline ColorComponent blend_components(ColorComponent origin, ColorComponent target, TimeVector frame) {
7 // https://www.youtube.com/watch?v=LKnqECcg6Gw 6 // https://www.youtube.com/watch?v=LKnqECcg6Gw
@@ -21,7 +20,7 @@ void blender_blend_canvas(Canvas *canvas, Canvas *source, Canvas *target, Morphi
21 CartesianMapping mapping; 20 CartesianMapping mapping;
22 Color pixel; 21 Color pixel;
23 22
24 dim = morpher_get_dim(morphing); 23 dim = morphing->dim;
25 24
26 assert(dim.x > 0 && dim.y > 0); 25 assert(dim.x > 0 && dim.y > 0);
27 assert(vector_equals(dim, canvas_get_dim(canvas))); 26 assert(vector_equals(dim, canvas_get_dim(canvas)));
@@ -33,7 +32,7 @@ void blender_blend_canvas(Canvas *canvas, Canvas *source, Canvas *target, Morphi
33 point.x = flat_dim % dim.y; 32 point.x = flat_dim % dim.y;
34 point.y = flat_dim / dim.y; 33 point.y = flat_dim / dim.y;
35 34
36 mapping = morpher_get_point_mapping(morphing, point, frame); 35 mapping = (CartesianMapping) {point, point};
37 pixel = blend_colors(canvas_get_pixel(source, mapping.origin), canvas_get_pixel(target, mapping.target), frame); 36 pixel = blend_colors(canvas_get_pixel(source, mapping.origin), canvas_get_pixel(target, mapping.target), frame);
38 canvas_set_pixel(canvas, point, pixel); 37 canvas_set_pixel(canvas, point, pixel);
39 } 38 }
diff --git a/src/morpher/morphing.c b/src/morpher/morphing.c
new file mode 100644
index 0000000..2ab22d0
--- /dev/null
+++ b/src/morpher/morphing.c
@@ -0,0 +1,44 @@
1#include "morpher/morphing.h"
2#include "common/mem.h"
3
4static inline TriangleMap *init_trianglemap(IntVector width, IntVector height) {
5 TriangleMap *bottom_left = trianglemap_create(m(0, 0), m(0, height), m(width, height));
6 TriangleMap *top_right = trianglemap_create(m(0, 0), m(width, height), m(width, 0));
7 trianglemap_set_neighbors(bottom_left, NULL, NULL, top_right, top_right);
8 trianglemap_set_neighbors(top_right, bottom_left, NULL, NULL, NULL);
9 return bottom_left;
10}
11
12static inline TriangleMap *find_triangle(TriangleMap *start, CartesianVector target) {
13 TriangleMap *t = trianglemap_to(start, target);
14 return t == start ? t : find_triangle(t, target);
15}
16
17static inline void update_center(Morphing *m) {
18 m->center = find_triangle(m->center, v(m->dim.x / 2, m->dim.y / 2));
19}
20
21static inline void ensure_delaunay_neighborhood(TriangleMap *t) {
22 trianglemap_propagate_delaunay(t);
23 trianglemap_propagate_delaunay(t->next);
24 trianglemap_propagate_delaunay(t->next->next);
25}
26
27Morphing *morphing_create(IntVector width, IntVector height) {
28 Morphing *m = malloc_or_die(sizeof(Morphing));
29 m->dim = (CartesianVector) {width, height};
30 m->first = init_trianglemap(width, height);
31 m->center = m->first;
32 return m;
33}
34
35void morphing_destroy(Morphing *m) {
36 while (m->first != NULL) m->first = trianglemap_destroy(m->first);
37}
38
39void morphing_add_constraint(Morphing *m, CartesianVector origin, CartesianVector destination) {
40 TriangleMap *target = find_triangle(m->center, origin);
41 TriangleMap *split = trianglemap_split(target, (CartesianMapping) {origin, destination});
42 ensure_delaunay_neighborhood(split);
43 update_center(m);
44}
diff --git a/test/blender/blender.c b/test/blender/blender.c
index bf16dc6..f42322f 100644
--- a/test/blender/blender.c
+++ b/test/blender/blender.c
@@ -2,11 +2,11 @@
2#include <assert.h> 2#include <assert.h>
3 3
4static void test_canvas_blending() { 4static void test_canvas_blending() {
5 Morphing morphing; 5 Morphing *morphing;
6 Canvas origin, target, result; 6 Canvas origin, target, result;
7 CartesianVector sample_point = {13, 17}; 7 CartesianVector sample_point = {13, 17};
8 8
9 morpher_init(&morphing, 64, 64); 9 morphing = morphing_create(64, 64);
10 canvas_init(&origin, 64, 64); 10 canvas_init(&origin, 64, 64);
11 canvas_init(&target, 64, 64); 11 canvas_init(&target, 64, 64);
12 canvas_init(&result, 64, 64); 12 canvas_init(&result, 64, 64);
@@ -14,13 +14,13 @@ static void test_canvas_blending() {
14 canvas_set_pixel(&origin, sample_point, (Color) {{0xFF, 0xED, 0x00, 0x00}}); 14 canvas_set_pixel(&origin, sample_point, (Color) {{0xFF, 0xED, 0x00, 0x00}});
15 canvas_set_pixel(&target, sample_point, (Color) {{0x00, 0x47, 0xAB, 0x00}}); 15 canvas_set_pixel(&target, sample_point, (Color) {{0x00, 0x47, 0xAB, 0x00}});
16 16
17 blender_blend_canvas(&result, &origin, &target, &morphing, 0.125); 17 blender_blend_canvas(&result, &origin, &target, morphing, 0.125);
18 assert(color_equals(canvas_get_pixel(&result, sample_point), (Color) {{0xEE, 0xDF, 0x3C, 0x00}})); 18 assert(color_equals(canvas_get_pixel(&result, sample_point), (Color) {{0xEE, 0xDF, 0x3C, 0x00}}));
19 19
20 canvas_free(&result); 20 canvas_free(&result);
21 canvas_free(&target); 21 canvas_free(&target);
22 canvas_free(&origin); 22 canvas_free(&origin);
23 morpher_free(&morphing); 23 morphing_destroy(morphing);
24} 24}
25 25
26int main(int argc, char **argv) { 26int main(int argc, char **argv) {