1
0
Fork 0
mirror of https://git.coom.tech/drummyfish/small3dlib.git synced 2024-11-21 20:39:57 +01:00

Add other sin method

This commit is contained in:
Miloslav Ciz 2022-06-10 20:39:20 +02:00
parent da1b3914ca
commit e4fa1a714f

View file

@ -10,7 +10,7 @@
license: CC0 1.0 (public domain) license: CC0 1.0 (public domain)
found at https://creativecommons.org/publicdomain/zero/1.0/ found at https://creativecommons.org/publicdomain/zero/1.0/
+ additional waiver of all IP + additional waiver of all IP
version: 0.901d version: 0.902d
Before including the library, define S3L_PIXEL_FUNCTION to the name of the Before including the library, define S3L_PIXEL_FUNCTION to the name of the
function you'll be using to draw single pixels (this function will be called function you'll be using to draw single pixels (this function will be called
@ -83,16 +83,6 @@
vertical size (y) depends on the aspect ratio (S3L_RESOLUTION_X and vertical size (y) depends on the aspect ratio (S3L_RESOLUTION_X and
S3L_RESOLUTION_Y). Camera FOV is defined by focal length in S3L_Units. S3L_RESOLUTION_Y). Camera FOV is defined by focal length in S3L_Units.
y ^
| _
| /| z
____|_/__
| |/ |
-----[0,0,0]-|-----> x
|____|____|
|
|
Rotations use Euler angles and are generally in the extrinsic Euler angles in Rotations use Euler angles and are generally in the extrinsic Euler angles in
ZXY order (by Z, then by X, then by Y). Positive rotation about an axis ZXY order (by Z, then by X, then by Y). Positive rotation about an axis
rotates CW (clock-wise) when looking in the direction of the axis. rotates CW (clock-wise) when looking in the direction of the axis.
@ -180,6 +170,14 @@
#define S3L_USE_WIDER_TYPES 0 #define S3L_USE_WIDER_TYPES 0
#endif #endif
#ifndef S3L_SIN_METHOD
/** Says which method should be used for computing sin/cos functions, possible
values: 0 (lookup table, takes more program memory), 1 (Bhaskara's
approximation, slower). This may cause the trigonometric functions give
slightly different results. */
#define S3L_SIN_METHOD 0
#endif
/** Units of measurement in 3D space. There is S3L_FRACTIONS_PER_UNIT in one /** Units of measurement in 3D space. There is S3L_FRACTIONS_PER_UNIT in one
spatial unit. By dividing the unit into fractions we effectively achieve a spatial unit. By dividing the unit into fractions we effectively achieve a
fixed point arithmetic. The number of fractions is a constant that serves as fixed point arithmetic. The number of fractions is a constant that serves as
@ -907,6 +905,7 @@ static inline int8_t S3L_stencilTest(
#define S3L_SIN_TABLE_LENGTH 128 #define S3L_SIN_TABLE_LENGTH 128
#if S3L_SIN_METHOD == 0
static const S3L_Unit S3L_sinTable[S3L_SIN_TABLE_LENGTH] = static const S3L_Unit S3L_sinTable[S3L_SIN_TABLE_LENGTH] =
{ {
/* 511 was chosen here as a highest number that doesn't overflow during /* 511 was chosen here as a highest number that doesn't overflow during
@ -977,6 +976,7 @@ static const S3L_Unit S3L_sinTable[S3L_SIN_TABLE_LENGTH] =
(510*S3L_FRACTIONS_PER_UNIT)/511, (510*S3L_FRACTIONS_PER_UNIT)/511, (510*S3L_FRACTIONS_PER_UNIT)/511, (510*S3L_FRACTIONS_PER_UNIT)/511,
(510*S3L_FRACTIONS_PER_UNIT)/511, (510*S3L_FRACTIONS_PER_UNIT)/511 (510*S3L_FRACTIONS_PER_UNIT)/511, (510*S3L_FRACTIONS_PER_UNIT)/511
}; };
#endif
#define S3L_SIN_TABLE_UNIT_STEP\ #define S3L_SIN_TABLE_UNIT_STEP\
(S3L_FRACTIONS_PER_UNIT / (S3L_SIN_TABLE_LENGTH * 4)) (S3L_FRACTIONS_PER_UNIT / (S3L_SIN_TABLE_LENGTH * 4))
@ -1349,6 +1349,7 @@ void S3L_mat4Xmat4(S3L_Mat4 m1, S3L_Mat4 m2)
S3L_Unit S3L_sin(S3L_Unit x) S3L_Unit S3L_sin(S3L_Unit x)
{ {
#if S3L_SIN_METHOD == 0
x = S3L_wrap(x / S3L_SIN_TABLE_UNIT_STEP,S3L_SIN_TABLE_LENGTH * 4); x = S3L_wrap(x / S3L_SIN_TABLE_UNIT_STEP,S3L_SIN_TABLE_LENGTH * 4);
int8_t positive = 1; int8_t positive = 1;
@ -1371,10 +1372,37 @@ S3L_Unit S3L_sin(S3L_Unit x)
} }
return positive ? S3L_sinTable[x] : -1 * S3L_sinTable[x]; return positive ? S3L_sinTable[x] : -1 * S3L_sinTable[x];
#else
int8_t sign = 1;
if (x < 0) // odd function
{
x *= -1;
sign = -1;
}
x %= S3L_FRACTIONS_PER_UNIT;
if (x > S3L_FRACTIONS_PER_UNIT / 2)
{
x -= S3L_FRACTIONS_PER_UNIT / 2;
sign *= -1;
}
S3L_Unit tmp = S3L_FRACTIONS_PER_UNIT - 2 * x;
#define _PI2 ((S3L_Unit) (9.8696044 * S3L_FRACTIONS_PER_UNIT))
return sign * // Bhaskara's approximation
(((32 * x * _PI2) / S3L_FRACTIONS_PER_UNIT) * tmp) /
((_PI2 * (5 * S3L_FRACTIONS_PER_UNIT - (8 * x * tmp) /
S3L_FRACTIONS_PER_UNIT)) / S3L_FRACTIONS_PER_UNIT);
#undef _PI2
#endif
} }
S3L_Unit S3L_asin(S3L_Unit x) S3L_Unit S3L_asin(S3L_Unit x)
{ {
#if S3L_SIN_METHOD == 0
x = S3L_clamp(x,-S3L_FRACTIONS_PER_UNIT,S3L_FRACTIONS_PER_UNIT); x = S3L_clamp(x,-S3L_FRACTIONS_PER_UNIT,S3L_FRACTIONS_PER_UNIT);
int8_t sign = 1; int8_t sign = 1;
@ -1385,9 +1413,7 @@ S3L_Unit S3L_asin(S3L_Unit x)
x *= -1; x *= -1;
} }
int16_t low = 0; int16_t low = 0, high = S3L_SIN_TABLE_LENGTH -1, middle;
int16_t high = S3L_SIN_TABLE_LENGTH -1;
int16_t middle;
while (low <= high) // binary search while (low <= high) // binary search
{ {
@ -1406,6 +1432,27 @@ S3L_Unit S3L_asin(S3L_Unit x)
middle *= S3L_SIN_TABLE_UNIT_STEP; middle *= S3L_SIN_TABLE_UNIT_STEP;
return sign * middle; return sign * middle;
#else
S3L_Unit low = -1 * S3L_FRACTIONS_PER_UNIT / 4,
high = S3L_FRACTIONS_PER_UNIT / 4,
middle;
while (low <= high) // binary search
{
middle = (low + high) / 2;
S3L_Unit v = S3L_sin(middle);
if (v > x)
high = middle - 1;
else if (v < x)
low = middle + 1;
else
break;
}
return middle;
#endif
} }
S3L_Unit S3L_cos(S3L_Unit x) S3L_Unit S3L_cos(S3L_Unit x)
@ -2244,7 +2291,6 @@ void S3L_drawTriangle(
#endif #endif
// draw the row -- inner loop: // draw the row -- inner loop:
for (S3L_ScreenCoord x = lXClipped; x < rXClipped; ++x) for (S3L_ScreenCoord x = lXClipped; x < rXClipped; ++x)
{ {
int8_t testsPassed = 1; int8_t testsPassed = 1;
@ -2404,7 +2450,6 @@ if (_S3L_projectedTriangleState != 0)
p.barycentric[2] = newBarycentric[2]; p.barycentric[2] = newBarycentric[2];
} }
#endif #endif
S3L_PIXEL_FUNCTION(&p); S3L_PIXEL_FUNCTION(&p);
} // tests passed } // tests passed