Loading files
This file is pinned to the selected release. Download the original to open it in your design tool.
f2776db0eThis file is pinned to the selected release. Download the original to open it in your design tool.
#ifndef _AFFINE_TRANSFORM_H_
#define _AFFINE_TRANSFORM_H_
#include <stdint.h>
// Store unpacked affine transforms as signed 16.16 fixed point in the following order:
// a00, a01, b0, a10, a11, b1
// i.e. the top two rows of the matrix
// [ a00 a01 b0 ] [ a00 a01 b0 ]
// [ a01 a11 b1 ] [ a01 a11 b1 ]
// [ 0 0 1 ] [ 0 0 1 ]
// Then pack integers appropriately
typedef int32_t affine_transform_t[6];
const int32_t AF_ONE = 1 << 16;
static inline __attribute__((always_inline)) int32_t mul_fp1616(int32_t x, int32_t y)
{
int64_t result = (int64_t)x * y;
return result >> 16;
}
// result can not be == left or right
static inline void affine_mul(affine_transform_t result, const affine_transform_t left, const affine_transform_t right)
{
result[0] = mul_fp1616(left[0], right[0]) + mul_fp1616(left[1], right[3]);
result[1] = mul_fp1616(left[0], right[1]) + mul_fp1616(left[1], right[4]);
result[2] = mul_fp1616(left[0], right[2]) + mul_fp1616(left[1], right[5]) + left[2];
result[3] = mul_fp1616(left[3], right[0]) + mul_fp1616(left[4], right[3]);
result[4] = mul_fp1616(left[3], right[1]) + mul_fp1616(left[4], right[4]);
result[5] = mul_fp1616(left[3], right[2]) + mul_fp1616(left[4], right[5]) + left[5];
}
static inline void affine_copy(affine_transform_t dst, const affine_transform_t src)
{
for (int i = 0; i < 6; ++i)
dst[i] = src[i];
}
// User is describing a sequence of transformations from texture space to
// screen space, which are applied by premultiplying a column vector. However,
// hardware transforms *from* screenspace *to* texture space, so we want the
// inverse of the transform the user is building. Therefore our functions each
// produce the inverse of the requested transform, and we apply transforms by
// *post*-multiplication.
static inline void affine_identity(affine_transform_t current_trans)
{
int32_t tmp[6] = {
AF_ONE, 0, 0,
0, AF_ONE, 0
};
affine_copy(current_trans, tmp);
}
static inline void affine_translate(affine_transform_t current_trans, int32_t x, int32_t y)
{
int32_t tmp[6];
int32_t transform[6] = {
AF_ONE, 0, -AF_ONE * x,
0, AF_ONE, -AF_ONE * y
};
affine_mul(tmp, current_trans, transform);
affine_copy(current_trans, tmp);
}
// TODO this is shit
const int32_t sin_lookup_fp1616[256] = {
0x0, 0x648, 0xc8f, 0x12d5, 0x1917, 0x1f56, 0x2590, 0x2bc4, 0x31f1, 0x3817,
0x3e33, 0x4447, 0x4a50, 0x504d, 0x563e, 0x5c22, 0x61f7, 0x67bd, 0x6d74,
0x7319, 0x78ad, 0x7e2e, 0x839c, 0x88f5, 0x8e39, 0x9368, 0x987f, 0x9d7f,
0xa267, 0xa736, 0xabeb, 0xb085, 0xb504, 0xb968, 0xbdae, 0xc1d8, 0xc5e4,
0xc9d1, 0xcd9f, 0xd14d, 0xd4db, 0xd848, 0xdb94, 0xdebe, 0xe1c5, 0xe4aa,
0xe76b, 0xea09, 0xec83, 0xeed8, 0xf109, 0xf314, 0xf4fa, 0xf6ba, 0xf853,
0xf9c7, 0xfb14, 0xfc3b, 0xfd3a, 0xfe13, 0xfec4, 0xff4e, 0xffb1, 0xffec,
0x10000, 0xffec, 0xffb1, 0xff4e, 0xfec4, 0xfe13, 0xfd3a, 0xfc3b, 0xfb14,
0xf9c7, 0xf853, 0xf6ba, 0xf4fa, 0xf314, 0xf109, 0xeed8, 0xec83, 0xea09,
0xe76b, 0xe4aa, 0xe1c5, 0xdebe, 0xdb94, 0xd848, 0xd4db, 0xd14d, 0xcd9f,
0xc9d1, 0xc5e4, 0xc1d8, 0xbdae, 0xb968, 0xb504, 0xb085, 0xabeb, 0xa736,
0xa267, 0x9d7f, 0x987f, 0x9368, 0x8e39, 0x88f5, 0x839c, 0x7e2e, 0x78ad,
0x7319, 0x6d74, 0x67bd, 0x61f7, 0x5c22, 0x563e, 0x504d, 0x4a50, 0x4447,
0x3e33, 0x3817, 0x31f1, 0x2bc4, 0x2590, 0x1f56, 0x1917, 0x12d5, 0xc8f, 0x648,
0x0, 0xfffff9b8, 0xfffff371, 0xffffed2b, 0xffffe6e9, 0xffffe0aa, 0xffffda70,
0xffffd43c, 0xffffce0f, 0xffffc7e9, 0xffffc1cd, 0xffffbbb9, 0xffffb5b0,
0xffffafb3, 0xffffa9c2, 0xffffa3de, 0xffff9e09, 0xffff9843, 0xffff928c,
0xffff8ce7, 0xffff8753, 0xffff81d2, 0xffff7c64, 0xffff770b, 0xffff71c7,
0xffff6c98, 0xffff6781, 0xffff6281, 0xffff5d99, 0xffff58ca, 0xffff5415,
0xffff4f7b, 0xffff4afc, 0xffff4698, 0xffff4252, 0xffff3e28, 0xffff3a1c,
0xffff362f, 0xffff3261, 0xffff2eb3, 0xffff2b25, 0xffff27b8, 0xffff246c,
0xffff2142, 0xffff1e3b, 0xffff1b56, 0xffff1895, 0xffff15f7, 0xffff137d,
0xffff1128, 0xffff0ef7, 0xffff0cec, 0xffff0b06, 0xffff0946, 0xffff07ad,
0xffff0639, 0xffff04ec, 0xffff03c5, 0xffff02c6, 0xffff01ed, 0xffff013c,
0xffff00b2, 0xffff004f, 0xffff0014, 0xffff0000, 0xffff0014, 0xffff004f,
0xffff00b2, 0xffff013c, 0xffff01ed, 0xffff02c6, 0xffff03c5, 0xffff04ec,
0xffff0639, 0xffff07ad, 0xffff0946, 0xffff0b06, 0xffff0cec, 0xffff0ef7,
0xffff1128, 0xffff137d, 0xffff15f7, 0xffff1895, 0xffff1b56, 0xffff1e3b,
0xffff2142, 0xffff246c, 0xffff27b8, 0xffff2b25, 0xffff2eb3, 0xffff3261,
0xffff362f, 0xffff3a1c, 0xffff3e28, 0xffff4252, 0xffff4698, 0xffff4afc,
0xffff4f7b, 0xffff5415, 0xffff58ca, 0xffff5d99, 0xffff6281, 0xffff6781,
0xffff6c98, 0xffff71c7, 0xffff770b, 0xffff7c64, 0xffff81d2, 0xffff8753,
0xffff8ce7, 0xffff928c, 0xffff9843, 0xffff9e09, 0xffffa3de, 0xffffa9c2,
0xffffafb3, 0xffffb5b0, 0xffffbbb9, 0xffffc1cd, 0xffffc7e9, 0xffffce0f,
0xffffd43c, 0xffffda70, 0xffffe0aa, 0xffffe6e9, 0xffffed2b, 0xfffff371,
0xfffff9b8
};
static inline int32_t sin_fp1616(uint8_t theta)
{
return sin_lookup_fp1616[theta];
}
static inline int32_t cos_fp1616(uint8_t theta)
{
return sin_lookup_fp1616[(theta + 64) & 0xff];
}
// Appears as a counterclockwise rotation (when viewed from texture space to screen space)
// Units of angle are 256 = one turn
static inline void affine_rotate(affine_transform_t current_trans, uint8_t theta)
{
int32_t tmp[6];
int32_t transform[6] = {
cos_fp1616(theta), -sin_fp1616(theta), 0,
sin_fp1616(theta), cos_fp1616(theta), 0
};
affine_mul(tmp, current_trans, transform);
affine_copy(current_trans, tmp);
}
static inline void affine_scale_reciprocal(affine_transform_t current_trans, int32_t scale_reciprocal) {
int32_t tmp[6];
int32_t transform[6] = {
scale_reciprocal, 0, 0,
0, scale_reciprocal, 0
};
affine_mul(tmp, current_trans, transform);
affine_copy(current_trans, tmp);
}
#endif // _AFFINE_TRANSFORM_H_