Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Time: f64 -> f32 #225

Closed
ozkriff opened this issue Aug 31, 2016 · 0 comments
Closed

Time: f64 -> f32 #225

ozkriff opened this issue Aug 31, 2016 · 0 comments

Comments

@ozkriff
Copy link
Owner

ozkriff commented Aug 31, 2016

Short version: I didn't know that "In Windows Contains a 64-bit value representing the number of 100-nanosecond intervals since January 1, 1601 (UTC)." =\


Добрый день. Меня зовут Андрей, мне 25 и сегодня я узнал что я ничего не знаю про плавающую точку и виндовое время. Может, все кроме меня это все уже и знают, но я все равно распишу в подробностях.

Итак, до прошлой недели со временем в игре все было отлично на всех платформах.

У меня уже довольно давно была заведена структура Time, которая хранила внутри время в наносекундах как его и возвращает time::precise_time_ns() - в u64.

Но однажды мне внезапно надоело что я везде таскаю практически голые наносекунды в u64. Мне-то время нужно только для вычисления состояния всяких анимаций (игровая логика работает только с командами/событиями/ходами, которые с реальным временем никак не связаны), так мне при каждом использовании таймеров надо было делить из значение на миллиард (столько наносекунд в секунде) и приводить к f32.

Я решил эту логику сконцентрировать в самом классе Time: dbb5817c - заменил u64 на f32 и спрятал сложнейшую математику деления на миллиард внутрь Time::now. Закомитил, запушил и довольный пошел дальше работать над вертолетами (#111).

Я почти все время работаю под убунтой, в винду только изредка захожу поиграть, так что о косяке мне написал @Vinatorul, которому стало интересно посмотреть на летающий над деревьями джип.

Сначала он меня жутко напугал словами "у меня тут три кадра в секунду", я уже представил как приятно будет разбираться что там в винде сломалось.

Потом он сказал что у меня прозрачность дыма и тумана войны сходят с ума:

кривой туман

кривой туман и дым

И я совсем приуныл, решил что при реализации плавного тумана войны (#210) убил производительность и опять какие-то косяки с альфа-каналом и отладка будет еще веселей.

Но @Vinatorul решил меня еще добить сообщением о том, что камера двигается-вертится с нормальной скоростью, тормозят только все анимации. - Как так?!

Я оперативно "решил" проблему в лоб, без особых размышлений заменив f32 в Time на f64: d3eee7. После этого комита @Vinatorul сказал что у него все починилось.


Все опять заработало, почему я не успокоился? Потому что мне не нравится появление f64 - до этого комита его в коде игры вообще не было и все дробные числа представлялись как f32. Четыре байта на таймер мне совсем не жалко, но очень неприятно что теперь надо обмазывать любое использование таймеров кучей преобразований as f32 =\ . А переводить все числа в f64 тоже так себе вариант - тут уже и правда с объемом данных могут сложности возникнуть, особенно при их пересылке в видеокарту.

Первое что пришло мне в голову - попробовать сдвинуть этап деления на миллиард на время работы с u64. Типа, так я избавляюсь от большого количества цифр в мантиссе и f32 должен справиться. Но извращение с заменой

Time{n: time::precise_time_ns() as f64 / 1_000_000_000.0}

на

let ns = time::precise_time_ns();
let ns_in_sec = 1_000_000_000;
let secs = (ns / ns_in_sec) as f32;
let subsecs = (ns % ns_in_sec) as f32 / ns_in_sec as f32;
Time{n: secs + subsecs}

все опять сломало на винде.

Посовещался с @Vinatorul и узнал что в винде, судя по http://stackoverflow.com/questions/5471379/ways-to-convert-unix-linux-time-to-windows-time, время хранится с 1600 какого-то там года О.о . В юникстайм-то наносекунды хранятся только с 1970ого года, т.е. виндовое количество наносекунд на три порядка превышает юниксовое! Никогда до этого не сталкивался с виндовым временем О.о

Отладочный вывод на винде и линуксе на это тоже намекал как мог:

Винда:

Линукс:

. . .
5178, 0.9530237
5178, 0.98814213
5179, 0.024250964
5179, 0.052965473
. . .

Само собой, точности f32 совсем не хватает для нормального хранения даже первой цифры после запятой в таком огромном числе и получаются "рывки" по 0.5 секунды - визуально это выглядит как 2-3 кадра в секунду.


Текущее направление мыслей:

В структуре Context (где у меня и так свалено все общее состояние графики) хранить время старта приложения в u64. Функцию now перенести из Time в Context и обозвать current_time. В этой функции получать текущее время в виде u64, вычитать из него время старта приложения (которое хранится в Context), затем уже переводить в f32 и делить на миллиард.

Кстати, зачем мне вообще extern crate time? Надо давно уже было на std::time перейти, он уже нцать месяцев как стабилизирован.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant