=A=L=X=
> Такое значение странновато.
Вообще-то, самый очевидный вариант. ±2^15 в int16_t не представимо, поэтому берем ±2^14.
}:+()___ [Smile]
А ну да, бит знака же еще.
Последние строки массива phdsintab
dw 3FB1h,3FB4h,3FB6h,3FB8h dw 3FBBh,3FBDh,3FBFh,3FC1h dw 3FC4h,3FC6h,3FC8h,3FCAh dw 3FCCh,3FCEh,3FD0h,3FD2h dw 3FD4h,3FD5h,3FD7h,3FD9h dw 3FDBh,3FDCh,3FDEh,3FE0h dw 3FE1h,3FE3h,3FE4h,3FE6h dw 3FE7h,3FE8h,3FEAh,3FEBh dw 3FECh,3FEDh,3FEFh,3FF0h dw 3FF1h,3FF2h,3FF3h,3FF4h dw 3FF5h,3FF6h,3FF7h,3FF7h dw 3FF8h,3FF9h,3FFAh,3FFAh dw 3FFBh,3FFCh,3FFCh,3FFDh dw 3FFDh,3FFEh,3FFEh,3FFEh dw 3FFFh,3FFFh,3FFFh,4000h dw 4000h,4000h,4000h,4000h dw 4000h,4000h
А так это 16384 равно в шестнадцатеричном виде 4000h. Ясно.
Так я так и понял что значения от 0 до 16384 мапятся на значения от 0 до 1.
Вообще как по мне так всё-таки немного спорно, что они возвращают результат не в 16:16, а в 18:14.
Технически скорее всего это вызвано желанием работать с нижним словом не учитывая никак вообще верхнее слово.
Тогда действительно нам нужно в нижнем слове иметь место под знак (1 бит) и чтобы выразить +1 еще один бит под целое число.
Но код явно говорит нам, что работаем мы в 32 битах где наиболее естественно работать с двойными словами.
Я бы поэтому на их месте сдвигал бы результат чтобы было "натуральное" 16:16 как на входе.
Вообще странно что разные форматы используются. У нас 0x10000 это или единица или pi для углов.
#define GAME_FOV 80 #define ONE_DEGREE 182 float one = (256.0f * 8.0f * 16384.0f); AlterFOV( GAME_FOV*ONE_DEGREE); void AlterFOV( PHD_ANGLE fov ) { fov/=2; phd_persp=( ( phd_winwidth/2)*phd_cos( fov))/phd_sin( fov); phd_oopersp = sint32( one)/phd_persp; f_persp=float( phd_persp); f_oneopersp=one/f_persp; f_perspoznear=f_persp/f_znear; float fAspect=float( phd_winwidth)/float( phd_winheight); float fDesiredAspect=4.0f/3.0f; LfAspectCorrection=fDesiredAspect/fAspect; }
Вопрос по тем же углам. Кто мне объяснит что такое float one и что такое phd_persp, phd_oopersp, f_perspoznear? Тут в коде имеется ввиду phd_winwidth = 640 т.е. ширина окна где работает приложение (640 на 480).
Тут по поводу phd_persp когда косинус делится на синус это котангентс, но что это дает?
SmoothBoy
fixed арифметика заключается в довольно простой идее - мы какую то левую часть бит целого int считаем за биты означающие целую часть, а всё что справа от них как дробную часть после запятой.
Например в 16-битном int16 можем сказать, что 8 верхних (левых) бит это целая часть, а 8 нижних (правых) бит - это дробная часть.
Чтобы получить целую часть нам теперь достаточно сдвинуть число вправо на количество бит в дробном части (выместить их). А ведь это то же самое, что деление числа на степень двойки количества этих вытесняемых бит.
На языке математики это можно перефразировать так, что мы число представляем как рациональное число у которого делимое - наше int16, а делитель - 2^8, т.е. 256.
Например (в десятичной системе) 500 в этой трактовке подразумевает 500/256, т.е. ~1,9531.
А 512 это 512/256 - просто 2.
А 1 это 1/256 = 0,00390625 - мельчайшее положительное число большее нуля в fixed 8:8.
Складываются числа одинаковой разрядности fixed аболютно просто и естественно, т.к. оба в уме поделены на одно и то же число, а значит и результат так же в уме остаётся на него поделенным без проблем.
Но вот с умножением возникает необходимость поправки - будучи перемноженными как обычные целые числа fixed "плывут в разделителе дробной и целой части".
Это легко увидеть если перемножить 256 (т.е. единицу) на 256 (единицу же) - получится 65536, а надо получить 256. И получить его легко - достаточно уже не в уме, а на практике разделить на одно из входящих в умножение 1/256 чтобы (и это важно) получить fixed разрядности второго аргумента (делитель которого уже опять держится в уме!).
Таким образом если у нас есть fixed A:B и мы умножаем его на fixed X:Y, то получившееся целое число надо сдвинуть вправо на B бит (разделить на 2^B) чтобы получить fixed X:Y или сдвинуть на Y бит чтобы получить fixed A:B. А само по себе умножение fixed A:B на fixed X:Y является fixed :B*Y
Если идея понятна, то вот какой вывод следует: в принципе вычисления с fixed можно проводить со скользящей точностью после запятой где надо чего то сдвигая и пододвигая.
И вот глядя на этот "one" без остального кода я бы сказал, что это единица когда мы держим в уме 1/(2^25), т.е. число fixed 7:25.
Но тут надо по хорошему и на другой код смотреть ибо вилами по воде писано. Но это непростой будет код судя по всему.
SmoothBoy
> #define GAME_FOV 80
> #define ONE_DEGREE 182
>
> AlterFOV(GAME_FOV*ONE_DEGREE);
фов=80
один градус=182
альтернативное фов=фов*градус
fov=field off view поле зрения камеры=гугли=80
один град=180град= это 180 градусов просмотр всего фронта наверно.
альтер=фов*град
наверное вторая альтернативная камера
наверное он кодировал там обзор камеры
Спасибо огромное за ответы. Есть еще такой код:
#include <Windows.h> #include <iostream> typedef short int PHD_ANGLE; #define WIBBLE_SIZE 32 #define MAX_WIBBLE 2 #define W2V_SHIFT 14 // Shift scale of View.Frame to World.Frame float wibble_table[WIBBLE_SIZE]; extern "C" int __fastcall phd_sin(int angle); int main( ) { int i, sn; PHD_ANGLE angle; for ( i = 0; i < WIBBLE_SIZE; i++) { angle = ( i * 65536) / WIBBLE_SIZE; sn = phd_sin( angle); wibble_table[i] = ( float)( sn * MAX_WIBBLE >> W2V_SHIFT); } return 0; }
Что делает этот код - заполняет значениями wibble_table - потом эта таблица используется для расчета координаты Y всех вершин каждого треугольника - это создает волны на поверхности, для эффекта воды. То есть wibble_table используется для создания волнистой поверхности, внешне это волны на море в игре.
Меня в этом коде интересует что такое и зачем W2V_SHIFT? В комментариях сказано Shift scale of View.Frame to World.Frame я что то не понимаю тут про матрицы вида и мира говорится или что?