Задачка имеет решение, надо лишь подумать как грамотно сделать.
Добавлено 02-10-2019 в 16:55:
Придумал. Перед началом основного кадра дллка добавляет список всех энтить для отрисовки в произвольном порядке, причём сами эти энтити могут быть вообще чем угодно, необязательно эдиктами. Могут и темп-энтити быть, например. Но при условии что эти объекты наследуются от абстрактного класса IRenderEntity. Примерно такого:
C++ Source Code:
1
class IRenderEntity
2
{
3
public:
4
~IRenderEntity() {}
5
virtualbool CheckVisibility( const ref_viewpass_t *view ) const = 0; // entity is present for this viewpass
virtualconst IModelBase *GetRenderModel( void ) const = 0; // get model for rendering
12
};
А дальше рендерер уже сам их сортирует в плане прозрачности или для мультипроходности, вызывая вот эти каллбэки. Рендеру для успешной отрисовки в сущности нужно не так уж и много информации от энтить - вышеперечисленное и несколько локальных параметров, типа рендерколора, номера кадра (спрайты/брашы). Ну чот типа такого.
Это набросок. не окончательный вариант конечно.
Плюс в том, что все интеракции останутся в описании самих энтить, не придётся на клиенте городить огород, мучительно угадывая, кто это был на сервере и в какие поля у него какие номера эдиктов и флагов сохранены.
Добавлено 02-10-2019 в 17:43:
Вообщем с точки зрения пользователя клиентская часть (конструктивно объединённая с серверной в единой дллке) выглядит следующим образом:
CreateMove - тут обрабатываем нажатия клавиш
ClientReadSnapshot - получаем обновления с сервера
ClientRunFrame - предиктинг всех энтить (у которых это настроено)
AddRenderEntities - здесь считаем видимую позицию в мире (с учётом предиктинга, интерполяции, сетапим все кости и прочее).
дальше движок всё это сортирует и рендерит не обращаясь в пользовательскую юиблиотеку, но вызывая виртуальные методы в классах самих объектов. Методы все константные, т.е. в них не производится никаких рассчётов, это всё должно быть сделано в AddRenderEntities.
Таким образом пользователь получает возможность полноценно управлять процессом рендеринга и в то же время не вклинивается своими вызовами в отрисовку кадра, что потенциально небезопасно, т.к. может сломать мультипроходной рендеринг. Смысл еще и в том, что сам пользователь ничего не знает об организации рендеринга, что там вообще происходит, отложка, форвард, это для него полностью прозрачно. Единственное что пока под вопросом - это возможность кастомного рендеринга в определённых случаях. Ну например отрисовка лучей. Но и тут достаточно просто выйти из положения - завести еще один метод в классе IRenderEntity, типа bool CustomRenderEntity();
и в нём производить отрисовку, но из самой отрисовки оставить только генерацию вертексов. То есть никаких шейдеров-материалов в этом методе использовано не будет. Это позволит иметь и кастомный рендеринг и в то же время сохранить абстрагирование на прежнем уровне. По похожей схеме можно будет организовать и рендеринг пост-процессов, где пользовательская сторона, сообразуясь с миром сможет спокойно забивать всю необходимую инфу для доф-прицела, а в кастомной функции отрисовки рендерить FSQ
А очерёдность отрисовки задавать через очередной каллбэк явно или неявно.
То есть мы решаем сразу две задачки - во первых оставляем за пользователем возможность нарисовать всякую фигню, а во вторых не заставляем его заботится о бакэнде. В принципе можно и HUD рисовать таким образом, почему нет.
Добавлено 02-10-2019 в 17:48:
ЗЫ. Если из вышесказанного непонятно - сетап костей у моделей целиком и полностью на совести пользователя. То есть всякие там джигглы, рагноллы, кастомные веровки, мерж-бонесы, инверсная кинематика - ну словом абсолютно всё находится в пользовательской части. Рендер просто запрашивает массив уже посчитанных костей.
Дядя Миша писал:
всякие там джигглы, рагноллы, кастомные веровки, мерж-бонесы, инверсная кинематика - ну словом абсолютно всё находится в пользовательской части
Какими средствами в пользовательской части можно будет палить игровое время и коллизию, чтобы трансформировать кости правильно?
Ну чтожы пришло время вплотную заняться модель-менеджером. В игровом коде кстати вот это тяжкое бредовое наследие из кваки, оно ведь не нужно совершенно. Я имею в виду эти магические пары PRECACHE_MODEL\SET_MODEL. Это имело смысл только для виртуальной машинки первокваки, поскольку она не могла обращаться со структурой model_t и там ввели модельиндексы для этого дела. Но на практике постоянно возникает необходимость считать какую-то информацию из модели. В халфовском сервере с этим очень грустно дела обстояли, на клиенте чуть полутьшы.
То есть там даже со всеми функциями, которые я ввёл, надо было сперва получить модельиндекс, потом по нему взять модель и только потом к ней обратиться. Всё это не нужно совершенно. Одной функции SetModel более чем достаточно. Прекэш можно оставить только для клиентских моделей, причём на клиент посылать не загадочный модельиндекс, а номер строки, который соответствует имени модели, чтобы потом на клиенте найти её по этому номеру. А модельиндексы соответственно вообще упразднить, они не нужны, как таковые. Точнее говоря в них был смысл, пока не было системы уникальных строк, идентификаторы которых куда как лучше справляются с заменой этих модельиндексов. Потому что эти таблицы репласемнтов по сути излишняя абстракция, которая была нужна только для сохранения совместимости.