====== Целочисленная тригонометрия ======
На PlayStation все вычисления рекомендуется производить в целочисленной арифметике, и синусы/косинусы - не исключение.
Самый эффективный способ реализации тригонометрии - таблица синусов. На самой консоли ничего вычислять не нужно, вместо этого функция sin просто обращается к таблице по индексу, полученному из угла. Таблица вычисляется заранее на ПК и сохраняется в виде массива из 16-битных целых. Чем больше таблица, тем выше угловая точность.
Пример программы на D, которая генерирует таблицу синусов для 4096 углов (8 KiB) в формате Q3.12:
import std.math: sin, PI, round;
import std.file: write;
enum COUNT = 4096;
enum SCALE = 0x1000;
void main()
{
ubyte[] data;
data.length = COUNT * 2;
foreach (i; 0..COUNT)
{
double angle = 2.0 * PI * i / COUNT;
short value = cast(short)round(sin(angle) * SCALE);
data[i * 2 + 0] = cast(ubyte)(value & 0xff);
data[i * 2 + 1] = cast(ubyte)(value >> 8);
}
write("sin4096.bin", data);
}
Функция чтения на C:
short sin(uint angle)
{
return sinTable[angle & 0xfff];
}
Косинус реализуется аналогично, но со сдвигом по фазе:
#define HPI 0x400
short cos(uint angle)
{
return sinTable[(angle + HPI) & 0xfff];
}
Число PI в Q3.12 будет равно 0x800.
Точность метода достаточна для представления поворотов в 3D-играх. Чем больше угловая скорость, тем менее заметны артефакты дискретности.