Add a blend pattern that maps to two individual patterns

This commit is contained in:
Zachary D. Rowitsch 2020-11-11 23:49:31 -05:00
parent d5ba13b2fe
commit 0ee822046b
4 changed files with 88 additions and 7 deletions
demo
module_patterns
test/module_patterns

@ -12,20 +12,24 @@
CEXCEPTION_T global_exception;
void build_world(WORLD_World* world) {
TUPLES_Color red, green, blue;
TUPLES_Color red, green, blue, black, gray, white;
TUPLES_init_color(&red, 1, 0, 0);
TUPLES_init_color(&green, 0, 1, 0);
TUPLES_init_color(&blue, 0, 0, 1);
PLANE_Plane* floor = PLANE_new();
TUPLES_init_color(&black, 0, 0, 0);
TUPLES_init_color(&gray, .25, .25, .25);
TUPLES_init_color(&white, 1, 1, 1);
PLANE_Plane* floor = PLANE_new();
WORLD_add_object(world, floor);
MATERIAL_Material* material = MATERIAL_new();
material->specular = 0;
PATTERN_Pattern* floor_pattern = PATTERN_new_stripe(&red, &green);
MATRIX_Matrix* pattern_transform = MATRIX_new_rotation_y(-M_PI / 5);
PATTERN_set_transform(floor_pattern, pattern_transform);
MATRIX_delete(pattern_transform);
PATTERN_Pattern* floor_pattern_a = PATTERN_new_stripe(&white, &gray);
PATTERN_Pattern* floor_pattern_b = PATTERN_new_stripe(&white, &gray);
MATRIX_Matrix *rot_y = MATRIX_new_rotation_y(M_PI_4);
PATTERN_set_transform(floor_pattern_b, rot_y);
MATRIX_delete(rot_y);
PATTERN_Pattern *floor_pattern = PATTERN_new_blended(floor_pattern_a, floor_pattern_b);
MATERIAL_set_pattern(material, floor_pattern);
PATTERN_delete(floor_pattern);
PLANE_set_material(floor, material);
MATERIAL_delete(material);

@ -66,6 +66,7 @@ static void copy_base_pattern_in_place(PATTERN_Pattern *dest, const PATTERN_Patt
MATRIX_copy(dest->inverse_transform, src->inverse_transform);
dest->at = src->at;
dest->copy = src->copy;
dest->delete = src->delete;
}
const TUPLES_Color *PATTERN_get_color_a(const PATTERN_Pattern *pattern) {
@ -311,6 +312,7 @@ void cube_map_at(TUPLES_Color *dest, const PATTERN_Pattern *pattern, const TUPLE
static PATTERN_Pattern *copy_cube_map(const PATTERN_Pattern *pattern) {
assert(pattern);
PATTERN_Pattern_Cube_Map *cube_map = (PATTERN_Pattern_Cube_Map*)pattern;
copy_base_pattern_in_place(&cube_map->pattern, pattern);
return PATTERN_new_cube_map(cube_map->uv_pattern[UV_PATTERN_LEFT],
cube_map->uv_pattern[UV_PATTERN_FRONT],
cube_map->uv_pattern[UV_PATTERN_RIGHT],
@ -355,3 +357,62 @@ PATTERN_Pattern *PATTERN_new_cube_map(const UV_Pattern *left, const UV_Pattern *
return (PATTERN_Pattern*)map;
}
//---- blended patterns
typedef struct {
PATTERN_Pattern pattern;
PATTERN_Pattern *a;
PATTERN_Pattern *b;
} PATTERN_Pattern_Blended;
void blended_map_at(TUPLES_Color *dest, const PATTERN_Pattern *pattern, const TUPLES_Point *point) {
assert(dest);
assert(pattern);
assert(point);
PATTERN_Pattern_Blended *bpat = (PATTERN_Pattern_Blended*)pattern;
TUPLES_Point pattern_a_point, pattern_b_point;
MATRIX_multiply_tuple(&pattern_a_point, bpat->a->inverse_transform, point);
MATRIX_multiply_tuple(&pattern_b_point, bpat->b->inverse_transform, point);
TUPLES_Color a_color, b_color;
PATTERN_color_at(&a_color, bpat->a, &pattern_a_point);
PATTERN_color_at(&b_color, bpat->b, &pattern_b_point);
TUPLES_add(dest, &a_color, &b_color);
TUPLES_divide(dest, dest, 2);
}
static PATTERN_Pattern *copy_blended_map(const PATTERN_Pattern *pattern) {
assert(pattern);
PATTERN_Pattern_Blended *bpat = (PATTERN_Pattern_Blended*)pattern;
PATTERN_Pattern *a = PATTERN_new_copy(bpat->a);
PATTERN_Pattern *b = PATTERN_new_copy(bpat->b);
PATTERN_Pattern *copy = PATTERN_new_blended(a, b);
copy_base_pattern_in_place(copy, pattern);
return copy;
}
static void delete_blended_map(PATTERN_Pattern *pattern) {
assert(pattern);
PATTERN_Pattern_Blended *bpat = (PATTERN_Pattern_Blended*)pattern;
PATTERN_delete(bpat->a);
PATTERN_delete(bpat->b);
delete_base_pattern(&bpat->pattern);
}
PATTERN_Pattern *PATTERN_new_blended(PATTERN_Pattern *a, PATTERN_Pattern *b) {
assert(a);
assert(b);
PATTERN_Pattern_Blended *pattern = malloc(sizeof(PATTERN_Pattern_Blended));
if (!pattern) {
Throw(E_MALLOC_FAILED);
}
TUPLES_Color dummy_color;
TUPLES_init_color(&dummy_color, 0, 0, 0);
PATTERN_init(&pattern->pattern, &dummy_color, &dummy_color);
pattern->pattern.at = &blended_map_at;
pattern->pattern.copy = &copy_blended_map;
pattern->pattern.delete = &delete_blended_map;
pattern->a = a;
pattern->b = b;
return (PATTERN_Pattern*)pattern;
}

@ -29,6 +29,7 @@ PATTERN_Pattern *PATTERN_new_checkers(const TUPLES_Color *a, const TUPLES_Color
PATTERN_Pattern *PATTERN_new_solid(const TUPLES_Color *a);
PATTERN_Pattern *PATTERN_new_map(const UV_Pattern* uv_pattern, void (*map)(double* u, double* v, const TUPLES_Point* point));
PATTERN_Pattern *PATTERN_new_cube_map(const UV_Pattern *left, const UV_Pattern *front, const UV_Pattern *right, const UV_Pattern *back, const UV_Pattern *up, const UV_Pattern *down);
PATTERN_Pattern *PATTERN_new_blended(PATTERN_Pattern *a, PATTERN_Pattern *b);
const TUPLES_Color *PATTERN_get_color_a(const PATTERN_Pattern *pattern);
const TUPLES_Color *PATTERN_get_color_b(const PATTERN_Pattern *pattern);

@ -260,6 +260,20 @@ void test_solid_pattern_is_always_same() {
PATTERN_delete(pattern);
}
void test_blended_pattern_takes_ownership_of_sub_patterns() {
TUPLES_Color *gray = TUPLES_new_color(.5, .5, .5);
PATTERN_Pattern *a = PATTERN_new_stripe(white, gray);
MATRIX_Matrix *rot_y = MATRIX_new_rotation_y(M_PI_2);
PATTERN_set_transform(a, rot_y);
MATRIX_delete(rot_y);
PATTERN_Pattern *b = PATTERN_new_stripe(white, gray);
TUPLES_delete(gray);
PATTERN_Pattern *blend = PATTERN_new_blended(a, b);
PATTERN_delete(blend);
}
int main(void) {
UNITY_BEGIN();
RUN_TEST(test_create_pattern);
@ -278,5 +292,6 @@ int main(void) {
RUN_TEST(test_checkers_repeat_in_y);
RUN_TEST(test_checkers_repeat_in_z);
RUN_TEST(test_solid_pattern_is_always_same);
RUN_TEST(test_blended_pattern_takes_ownership_of_sub_patterns);
return UNITY_END();
}