Целочисленная тригонометрия

На 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-играх. Чем больше угловая скорость, тем менее заметны артефакты дискретности.