-
Notifications
You must be signed in to change notification settings - Fork 90
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
Delta в игре понимается тремя взаимно противоречивыми способами. #609
Comments
Давайте рассудим всё основательно. Разделим формальные признаки (сам код) от неформальных (все остальные соображения). неформальныеЧто было бы логичнее? С точки зрения наименования "delta" - это больше похоже на расстояние между двумя пластами земли, она же высота пещеры. Что говорят авторы? По сообщению Андрея Кузьмина, была проблема:
По сообщению Александра Котляра, это толщина:
Как смотрится лучше? Похоже, что с толщиной смотрится лучше. Результат - смешаный. формальныеДавайте покопаемся в коде внимательно:
hd = *pa;
hu = *(pa + 1);
if((h = hu - hd) < 32){
SET_DELTA(*pf,0);
SET_DELTA(*(pf + 1),0);
}
else {
h -= 16;
if(h > MAX_RDELTA) h = MAX_RDELTA;
h = (h >> DELTA_SHIFT) - 1;
SET_DELTA(*pf,(h & 12) >> 2);
SET_DELTA(*(pf + 1),(h & 3));
}
} Здесь описана следующая логика: если расстояние между верхним и нижним слоем меньше 32, отнять 16 и закодировать её в дельте. Это похоже именно на высоту пещеры.
h = GET_UP_ALT(pf,*pa,pa0,x);
hy = GET_UP_ALT(pfy,*pay,pay0,x);
d = abs(h - hy);
if(d >= TunnelHeight){ ...
d = (d >> DELTA_SHIFT) - 1;
...
SET_DELTA(*pf,(d & 12) >> 2);
SET_DELTA(*(pf + 1),(d & 3));
...
} Опять же, разница между уровнями записывается в
int d = 32; Похоже, во всём модуле полагается дельта равная 32. К какой семантике больше подходит? Не ясно.
d = *(p -1);
if(d < z && (d + (((GET_DELTA(*(t - 1)) << 2) + GET_DELTA(*t) + 1) << DELTA_SHIFT)) > z) return 0; Тут вычисляется пересечение точки с ладшафтом. Совершенно ясно, что берётся трактовка дельты как высоты пещеры.
if((int)*(pa - 1) + (((GET_DELTA(*(pf - 1)) << 2) + GET_DELTA(*pf) + 1) << DELTA_SHIFT) >= h){ Но с уверенностью я сказать не решусь, что происходит в этом модуле.
#define GET_THICKNESS(p) ((GET_DELTA(*HIGH_LEVEL((p) + H_SIZE)) + (GET_DELTA(*LOW_LEVEL((p) + H_SIZE)) << 2) + 0) << DELTA_SHIFT) Вычисляется всё та же дельта, но результат называют "thickness", что могло бы означать толщину верхнего слоя. uintptr_t ll = *LOW_LEVEL(p);
return ll | (ll + (GET_THICKNESS(p) << 8)) | ((uintptr_t)(*HIGH_LEVEL(p)) << 16) | 0xff000000; Функция возвращает 3 отметки высоты: первый уровень, начало второго уровня, конец второго уровня. Явно видно, что "thickness" не вычитается из второго уровня, а прибавляется к первому. Это значит, что настоящий смысл данного макроса - вернуть высоту пещеры. Кроме того, это похоже на реальный баг. Смотри #610 с предлагаемым исправлением.
inline uchar GET_WIDTH(uchar* type, int x)
{
if(*type & DOUBLE_LEVEL){
if(x & 1)
return (((GET_DELTA(*(type - 1)) << 2) + GET_DELTA(*type) + 1) << DELTA_SHIFT);
else
return (((GET_DELTA(*type) << 2) + GET_DELTA(*(type + 1)) + 1) << DELTA_SHIFT);
}
return 0;
} Итак, она возвращает нашу закодированную дельту, также как и t = GETWIDTH(CX,CY);
status < "x:" <= CX < " y:" <= CY < " col: " <= *(vMap -> lineTcolor[CY] + CX);
status < " type: " <= GETTERRAIN(CX,CY);
if(dl) status < "/" <= GETDOWNTERRAIN(CX,CY);
if(!dl)
status < " alt:"<= u;
else {
d = GETDOWNALT(CX,CY);
status < " d:" <= d;
status < " u:"<= u;
status < " t:" <= t;
status < " w:" <= (u - d - t);
} Отсюда не ясно, что оно значит. Более того, похоже, что значение менялось. Есть ещё такая штука в этом же файле: const int DELTA = 16; Она не похожа на нашу дельту, используется везде. Скорее, это просто квант изменения любых высот в данном контексте.
итогиНеформальные доводы смешаны. В коде явно что-то менялось, и вполне возможно, что раньше кодировалась именно "thickness". Возможно, Котляр этот момент и вспомнил. Но в той версии, что у нас есть сейчас, всё прямо указывает на высоту пещеры, и логика surmap в этом согласна с 3Д физикой и всем остальным. На случайную ошибку не похоже. |
У меня есть возражения. Во-первых, я исхожу из того, что игру пишут не ради кода, а ради конечного результата. Соответственно, если мир выглядит искаженным, то это явно неправильное понимание кода. Тут есть и чисто практическая причина. Очевидно, когда разработчики рисовали мир, они рисовали провода прямымим, проемы под мостами широкие и т. д. В том числе просто вставляя 3d-модели в карты высот. Предположить что они во всех мирах везде одинаково ошиблись, маловероятно. Поэтому очевидно, что миры рисовались исходя из того, что delta это толщина верхнего слоя. Тени, которые (хотя это надо бы проверить) рисуются исходя и из ширины, и из толщины верхнего слоя, показывают провода прямыми. Если бы они рисовались исходя из дельты-пещеры, они бы были вытянутыми. Во-вторых, как я понял, ты просто почитал код, а я проверял, для чего он используется и где выполняется. Теперь подробнее:
Я согласен с тем, что код противоречив. Но визуально все выглядит так, что когда рисовали миры, дельту считали толщиной. Дальше действительно непонятно что происходило. Проблема в том, что когда мы начинаем рисовать миры с боку из позиции что дельта это высота пещеры, мы получаем уродливые миры. Когда считаем что толщина верхнего слоя, миры выглядят нормально. И дело не только в эстетике. Если считать физику исходя из высот, и считать дельту высотой пещеры, мы, проезжая под проводом на берегу реки, и въезжая под ним в реку, должны уткнуться в этот провод, которые начинает удлиняться резко вниз, что выглядит странно. Если в коде высота пещеры фиксированная, то все равно уткнемся. Если толщина верхнего слоя фиксированная, не уткнемся. Отсюда мой вывод, что уровни и визуально, и физически могут работать только если мы считаем дельту толщиной верхнего слоя или считаем толщину верхнего слоя фиксированной. |
Попробовал на потрошители проехать под проводом на берегу и заехать в воду. Мехос наткнулся на препятствие и наклонился вниз как будто провод реально вытянулся вниз. Выглядит будто реально работают то ли с дельтой, то ли с константой как высотой пещеры. Короче физика у нас противоречит логике. Проверил еще в сюрмапе. Начал наращивать верхний слой. w выросло, t осталось на месте. Начал наращивать нижний слой. t и w в процессе попеременно то увеличиваются то уменьшаются. Но судя по верхнему слою, t реально высота пещеры, а w наоборот толщина верхнего слоя. Получается, ты прав и сюрмап тоже так считает. Я признаю, что везде сейчас дельта это высота пещеры. Но это приводит и к кривому визуалу с вытягивающимися проводами и толстыми мостами, и к кривой физике, где ты натыкаешься на вытянутые провода над рекой. Короче, дельта = пещера это канонично, но выглядит и играется неправильно. |
Остался правда вопрос с тенями. Но как они считаются, понять невозможно. |
Сюрмап понимает дельту как толщину верхнего слоя, и, судя по всему, так и предполагалось изначально:
Vangers/src/terra/render.h
Lines 109 to 118 in 5a214b1
При рендеринге в 3d провода выглядят нормально:
Физика расчета пуль понимает дельту как высоту пещеры:
Vangers/src/units/hobj.cpp
Lines 1555 to 1564 in 5a214b1
При рендеринге в 3d провода вытянуты вниз:
Физика расчета 3d объектов вообще игнорирует дельту и использует фиксированную ширину верхнего слоя:
Vangers/src/3d/dynamics.cpp
Line 67 in 5a214b1
Визуализации в 3d третьего способа нет.
The text was updated successfully, but these errors were encountered: