103 lines
2.4 KiB
C
103 lines
2.4 KiB
C
#pragma once
|
|
|
|
#include <assert.h>
|
|
#include "tuples.h"
|
|
#include "matrices.h"
|
|
|
|
enum pattern_type {
|
|
PATTERN_STRIPE,
|
|
PATTERN_GRADIENT,
|
|
PATTERN_RING,
|
|
PATTERN_CHECKERS
|
|
};
|
|
|
|
struct pattern {
|
|
enum pattern_type type;
|
|
struct tuple a;
|
|
struct tuple b;
|
|
struct mat4x4 transform;
|
|
};
|
|
|
|
inline static struct pattern stripe_pattern(struct tuple a, struct tuple b)
|
|
{
|
|
return (struct pattern) {
|
|
PATTERN_STRIPE,
|
|
a,
|
|
b,
|
|
mat4x4_identity()
|
|
};
|
|
}
|
|
|
|
inline static struct pattern gradient_pattern(struct tuple a, struct tuple b)
|
|
{
|
|
return (struct pattern) {
|
|
PATTERN_GRADIENT,
|
|
a,
|
|
b,
|
|
mat4x4_identity()
|
|
};
|
|
}
|
|
|
|
inline static struct pattern ring_pattern(struct tuple a, struct tuple b)
|
|
{
|
|
return (struct pattern) {
|
|
PATTERN_RING,
|
|
a,
|
|
b,
|
|
mat4x4_identity()
|
|
};
|
|
}
|
|
|
|
inline static struct pattern checkers_pattern(struct tuple a, struct tuple b)
|
|
{
|
|
return (struct pattern) {
|
|
PATTERN_CHECKERS,
|
|
a,
|
|
b,
|
|
mat4x4_identity()
|
|
};
|
|
}
|
|
|
|
inline static struct tuple stripe_at(struct pattern pattern, struct tuple point)
|
|
{
|
|
return ((int)floorf(point.x)) % 2 == 0 ? pattern.a : pattern.b;
|
|
}
|
|
|
|
inline static struct tuple gradient_at(struct pattern pattern, struct tuple point)
|
|
{
|
|
struct tuple distance = tuple_sub(pattern.b, pattern.a);
|
|
float fraction = point.x - floorf(point.x);
|
|
|
|
return tuple_add(pattern.a, tuple_mul(distance, fraction));
|
|
}
|
|
|
|
inline static struct tuple ring_at(struct pattern pattern, struct tuple point)
|
|
{
|
|
return ((int)floorf(sqrtf(point.x * point.x + point.z * point.z))) % 2 == 0 ? pattern.a : pattern.b;
|
|
}
|
|
|
|
inline static struct tuple checkers_at(struct pattern pattern, struct tuple point)
|
|
{
|
|
return (int)(floorf(point.x) + floorf(point.y) + floorf(point.z)) % 2 == 0 ? pattern.a : pattern.b;
|
|
}
|
|
|
|
inline static struct tuple pattern_at_object(struct pattern pattern, struct mat4x4 object_transform, struct tuple point)
|
|
{
|
|
struct tuple object_point = mat4x4_mul_t(mat4x4_inverse(object_transform), point);
|
|
struct tuple pattern_point = mat4x4_mul_t(mat4x4_inverse(pattern.transform), object_point);
|
|
|
|
switch (pattern.type) {
|
|
case PATTERN_STRIPE:
|
|
return stripe_at(pattern, pattern_point);
|
|
case PATTERN_GRADIENT:
|
|
return gradient_at(pattern, pattern_point);
|
|
case PATTERN_RING:
|
|
return ring_at(pattern, pattern_point);
|
|
case PATTERN_CHECKERS:
|
|
return checkers_at(pattern, pattern_point);
|
|
default:
|
|
assert(false);
|
|
break;
|
|
}
|
|
}
|