Дядя Миша
Так, а что может быть непонятного в одной функции? Нет, ну если там помимо этого нужно ещё городить огород, то да.
Кстати вопрос немного не по теме, но всё же я хочу спросить тебя, по поводу парентов в халфе и спирите, почему с ними были такие трудности? Я насколько помню адекватно работающие паренты ты реализовал уже в ксашмоде только когда уже перенес его на ксашдвижок. Халфа не умеет работать с локальными пространствами? Интересен этот исторический момент.
И какова архитектура дочерних объектов будет в новом движке? Можно фрактально теже ротатабли друг в друга вложить?
__________________ Иван Топорышкин пошел на охоту,
С ним пудель пошел, перепрыгнув забор,
Иван, как бревно провалился в болото,
А пудель в реке утонул, как топор.
FiEctro писал: почему с ними были такие трудности?
Исторически преобразования пространства это тежолые матричные вычисления, компьютеры тогда не тянули, вот и не делали.
Я помню когда-то форк квейка на плейстейшон вита доделывал, решил ему замутить корректную трассу об ротатабли, ессно матричную. Так фпс после моей доработки упал вдвое
Цитата:
FiEctro писал: Я насколько помню адекватно работающие паренты ты реализовал уже в ксашмоде только когда уже перенес его на ксашдвижок.
Так физика была в движке зашита, а без переделки физики получались сплошные костыли. Можно было бы заморочиться и сделать адекватные паренты в халфе, просто из спортивного интереса, Ксерокс кажется делал в Хеткрап Френзи.
Цитата:
FiEctro писал: И какова архитектура дочерних объектов будет в новом движке? Можно фрактально теже ротатабли друг в друга вложить?
Вложенность есть иллюзия на самом-то деле. Под вложенностью понимается некоторый уровень наследования. Ну например, что дочерние объекты будут:
1. видны вместе с родительским
2. будут наследовать перемещения родительского объекта
3. будут удалены одновременно с родительским объектом
Какие еще условия можно тут унаследовать?
Наследование можно сделать через пространство имён так же как в С++, например. Это для доступа к таким объектам. Этот вопрос будет решаться во время создания редактора.
Дядя Миша писал: Исторически преобразования пространства это тежолые матричные вычисления, компьютеры тогда не тянули, вот и не делали.
Ну с костями же это всё работает, и для скелеталки это даже в халфе работало. Чем она отличаются от всех остальных объектов?
Цитата:
Дядя Миша писал: Какие еще условия можно тут унаследовать?
Позиция, угол, скейл.
Цитата:
Дядя Миша писал: Наследование можно сделать через пространство имён так же как в С++, например. Это для доступа к таким объектам. Этот вопрос будет решаться во время создания редактора.
В Юнити есть ещё такой прикол как префабы, это по сути отдельная сцена с объектами, которую ты можешь вставлять внутрь другой сцены. В том числе распаковывать префаб в обычные объекты сцены с учетом всех трансформаций что ты применял для префаба.
__________________ Иван Топорышкин пошел на охоту,
С ним пудель пошел, перепрыгнув забор,
Иван, как бревно провалился в болото,
А пудель в реке утонул, как топор.
FiEctro писал: это по сути отдельная сцена с объектами, которую ты можешь вставлять внутрь другой сцены.
В UE4 можно создать уровень в котором можно создавать еще уровни, типа слои, например, у нас есть основной левел и в нем еще несколько отдельных левелов с освещением, коллизией, звуками, и так далее
__________________
Kiss my ass if you don't like my Ford!
------------------------------------------ Game Area51 Update 1
First Person Shooter Released Jul 24, 2017
The game is a 3d shooter with the elements of the quest.
(_-=ZhekA=-_) писал: В UE4 можно создать уровень в котором можно создавать еще уровни, типа слои, например, у нас есть основной левел и в нем еще несколько отдельных левелов с освещением, коллизией, звуками, и так далее
Да у Юнити и УЕ примерно одинаковая логика, а в УЕ5 буквально с Юнити интерфейс слизали. Я когда зашел, даже офигел, сначала думал что не разберусь, а потом почти с набегу даже поимпортировал ресурсы, собрал небольшую сцену. Сразу видно хотят переманить к себе Юнитистов, и надо сказать у них хорошо получается.
__________________ Иван Топорышкин пошел на охоту,
С ним пудель пошел, перепрыгнув забор,
Иван, как бревно провалился в болото,
А пудель в реке утонул, как топор.
FiEctro писал: а в УЕ5 буквально с Юнити интерфейс слизали.
Почти сразу с ue4 пересел на ue5 и до сих пор матерюсь на новый дизайн редактора... Ппй какой не удобных после четверки... Но уже почти привык )))
Цитата:
FiEctro писал: Да у Юнити и УЕ примерно одинаковая логика
Хз, я юнити даже не запускал )
__________________
Kiss my ass if you don't like my Ford!
------------------------------------------ Game Area51 Update 1
First Person Shooter Released Jul 24, 2017
The game is a 3d shooter with the elements of the quest.
Дядя Миша писал: А зачем скейл наследовать? Приведи пример.
А зачем скейл наследуют кости? Ну например чтобы одновременно скейлить дочерние объекты с разным скейлом. Чем сидеть высчитывать отдельно для каждого. Можно ещё такие желеподобные штуки делать физические (софтбоди), и тоже их скейлить так удобно, поскольку они состоят из нескольких ригидбоди с джоинтами.
В Юнити кстати скелеталка это обычные игровые объекты с иерархией, т.е. к любой кости можно свободно прикрепить скрипт, объект, или вообще вытащить эту кость на сцену из иерархии. Ну или даже дополнить скелет новыми косточками прямо в самом редакторе Юнити, например чтобы добавить ИК контролеры.
Цитата:
Дядя Миша писал: Ну ты сравнил стек костей, который в кэш помещался для еденичного объекта и хаотично разбросанные по всей памяти.
А родитель разве не единичный объект? Как он по памяти хаотично разбросан может быть? Я думал все объекты хранятся в каком то едином массиве чтобы по ним легко можно было поиск делать. Особенно это актуально для сохранений и ченжлевелов.
__________________ Иван Топорышкин пошел на охоту,
С ним пудель пошел, перепрыгнув забор,
Иван, как бревно провалился в болото,
А пудель в реке утонул, как топор.
FiEctro писал: Как он по памяти хаотично разбросан может быть?
Каждый объект в той же халфе - это отдельный маллок, т.к. их размеры отличаются. Вот в кваке, там да, был единый гигантский массив.
Но я не только об этом. Кости в одной функции считались и массив там умещался в кэше, причём считался только для объектов, которые видны игроку.
А физика с парентами считалсь бы всегда и везде для всего мира.
Цитата:
FiEctro писал: Ну например чтобы одновременно скейлить дочерние объекты с разным скейлом.
Очевидно речь идёт не об абсолютном масштабе, а об относительном.
Т.е. исходный скейл у дочерних объектов может быть каким угодно, но если к родительскому будет применено его изменение, то и к дочерним тоже. Это да.
Цитата:
FiEctro писал: В Юнити кстати скелеталка это обычные игровые объекты с иерархией
Это еще с третьего дуума пошло Кармак был первым это придумал.
Цитата:
FiEctro писал: А родитель разве не единичный объект?
Всё относительно. Родитель может быть и чьим-то дочерним объектом одновременно.
Я вот как-то не задумывался, а теперь, так сказать столкнулся. Если мы объявляем статичный динамический массив внутри класса, очевидно, что его размер будет объявлен позднее, т.к. мы не можем проинициализировать этот массив прямо внутри класса. Однако функция, которая будет обращаться к этому массиву может находиться внутри тела класса. До тех пор пока она просто обращается к массиву никаких проблем не возникает. Но если мы попытаемся применить sizeof к такому вот оператору, то...
Проиллюстрирую на примере
C++ Source Code:
1
#define ARRAYSIZE( p ) (sizeof( p ) / sizeof( p[0] ))
2
struct test_t
3
{
4
constchar *name;
5
int value;
6
};
7
8
class CArrayTest
9
{
10
public:
11
static test_t m_entries[];
12
public:
13
void Test( void )
14
{
15
Msg( "arraysize: %d\n", ARRAYSIZE( m_entries ));
16
}
17
};
18
19
test_t CArrayTest :: m_entries[] =
20
{
21
{ "Test1", 1 },
22
{ "Test2", 2 },
23
{ "Test3", 3 },
24
};
Дело в том, как вы знаете, что sizeof срабатывает по месту вставки, немедленно. А у нас массив-то ещё непроинициализирован!!!! А функция, где его размер должен быть взят находится ВЫШЕ, чем инициализация массива, хотя бы потому, что С++ не позволяет инициализировать массивы, принадлежащие классу внутри его тела. Даже если это статичные массивы. Ну вот нельзя и всё тут. Таким образом, когда мы берём размер m_entries, он у нас равен []. И получаем ошибку
Цитата:
error C2070: illegal sizeof operand
Решение заключается в том, чтобы вынести функцию вычисления размера массива после, собственно, его инициализации. То есть вот так:
C++ Source Code:
1
#define ARRAYSIZE( p ) (sizeof( p ) / sizeof( p[0] ))
2
class CArrayTest
3
{
4
public:
5
static test_t m_entries[];
6
public:
7
void Test( void );
8
};
9
10
test_t CArrayTest :: m_entries[] =
11
{
12
{ "Test1", 1 },
13
{ "Test2", 2 },
14
{ "Test3", 3 },
15
};
16
17
void CArrayTest :: Test( void )
18
{
19
Msg( "arraysize: %d\n", ARRAYSIZE( m_entries ));
20
}
Этот вариант компилируется без проблем. Но мне стало любопытно. А может быть некоторые компиляторы настолько продвинутые, что используют подобие deferred sizeof? Проверьте пожалуйста первый вариант на различных компиляторах, как они себя поведут.
Пришла мне в голову вот какая идея. Всем известно что занулять класс с виртуальными методами при помощи memset нельзя - будет сплошной вылет, да и только. Не избежал этой участи и мой язык, хотя он конечно вылетает с помощью своих встроенных средств, а основное приложение продолжает свою работу. Но тем не менее. Какие у нас могут быть выходы из положения?
В целом моё предложение отдаёт парадигмой разработчиков компилятора GCC, поэтому хочу с вами посоветоваться. Итак, компилятор, допустим видит, что вызвали мемсет, зануляющий класс извнутри:
C++ Source Code:
1
Foo :: Foo()
2
{
3
memset( this, 0, sizeof( *this ));
4
}
Он конечно будет ориентироваться не по ключевому слову this, а по началу указателя и размеру зануляемых данных. Но выловить подобный вызов элементарно. Итак, какие у нас варианты:
1. если в классе есть виртуальные методы - вывести варнинг, что будет бида
2. автоматически сдвинуть указатель на начало пользовательских данных
3. ничего не делать, как MSVC и как оно сейчас
4. свой вариант?
Давно ничего не писал, немного отчитаюсь о проделанной работе, за которую автор, как известно - маладец.
1. сделаны шаблоны функций (до этого были только шаблоны классов)
2. переписан парсер выражений, приведён к стандарту С++, во всяком случае в плане приоритетов.
3. сделаны операторы и их перегрузка, включая new и delete, что в рамках виртуальной машины приобретает дополнительный смысловой контекст, о чём я непременно расскажу позже.
4. исправлено множество мелких ошибок, которые не выявлялись никакими юнит-тестами (их вообще правильнее называть регрессионные тесты), но стали попадаться при работе с реальными исходниками.
Осталось внедрить в язык последнюю конструкцию, которая есть в С++, а у меня пока ещё нет - это исключения. По идее на виртуальной машине такое должно реализовываться даже проще чем на С++ - заводим ещё один стек для исключений и дело в шляпе. Но проблема определения деструкторов, которые должны быть вызваны от этого никуда не исчезает, конечно.
Начал разбираться как устроен синтаксис. И выяснилось прекрасное. Есть две никак не связанные системы обработки исключений. Первая представлена словами: try, catch, throw, а вторая словами __try, __except, __finally. Особой пикантности добавляет тот факт, что в первом обработчике блока finally нет вообще. Уж не знаю, то ли это недоработка шестой студии, то ли соблюдение стандарта. Однако вот на сайте Мелкософта: https://learn.microsoft.com/ru-ru/c...p?view=msvc-170
Про него тоже ни слова. Это тем более интересно, если учесть, что в VCL-библиотеке наоборот всё держится именно на связке try, catch, finally
Мне кажется тут имеет место какое-то наслоение совместимости.
Надо выработать единый синтаксис, ну чтобы не путаться.
Добавлено 03-02-2023 в 13:54:
ЗЫ. Я чёт подумал, мож мне эти деструкторы просто коллекционировать в массив, а вызывать вручную, не бегая по коду и не проверяя, где они там должны быть вызваны? Хотя наверное нечто подобное и так делается, а при нормальной работе время уходит на то, чтобы найти указатель на очередной объект и выбросить его из списка при нормальном вызове деструктора. Ну что-то такое вообщем. Это пока просто размышления, т.к. я еще недостаточно погрузился в проблему.
Добавлено 03-02-2023 в 15:15:
Кажется дошло. Меня сбило с толку то, что в Делфи поддерживаются конструкции из трёх ключевых слов - try, except, finally, тогда как в С++ - только конструкции из двух слов, причём ключевого слова finally в механизме обработки исключений С++ нет. Оно есть только в микрософтовском расширении механизма обработки исключений для С, судя по всему построенному на лонг-джампах. Второй тип, как я понимаю, никаким-таким вызовом деструкторов не занимается и вообще про них ничего не знает.
А значит должен быть чуть более быстрым чем нативный С++ обработчик. https://learn.microsoft.com/ru-ru/c...t?view=msvc-170
Добавлено 03-02-2023 в 15:19:
А, вот, есть ещё слово __leave, которое сразу прыгает на секцию __finally.
Но это механизм для управления нормальным потоком выполнения, т.к. никаких исключений при этом не бросается. Просто удобный выход из цепочки вызванных функций.
Добавлено 03-02-2023 в 15:39:
Возможно далеко не всем (хотя кого я обманываю? практически никому) не интересно то, что я здесь пишу, поэтому для обычных пользователей тоже кое-что расскажу. Вчера я провёл одну из заключительных оптимизаций выполнения кода виртуальной машины и получил производительность, которая меня более или менее устроила. Если подходить к замерам в сугубо синтетических тестах, ну например таких, как итерация цикла на 10-20 миллионов, то виртуальная машина сливает С++ без вариантов. Раз в 10 медленее, а может быть и в сто. Однако, когда речь идёт о выполнении реального кода, всё далеко не так однозначно. Ведь мы так или иначе обращаемся к каким-то тяжёлым функциям, например к вызову отрисовки треугольников на экране, к открытию\чтению файла, а это всё делает запрос в системные вызовы и конечная скорость работы зачастую определяется именно временем работы этих вызовов, а не скоростью самой виртуальной машины. Так вот, по моим прикидкам, в реальных задачах, она у меня медленее ну где-то на треть реального кода. Разумеется с оговоркой, что виртуальная машина выполняет только тот код, который предзначен для модификации пользователем и поэтому на фоне остального кода, его сравнительно немного. Именно поэтому падение производительности столь незначительное и более чем приемлимое. Я опасался что будет просадка в 5-10 раз.
Дядя Миша писал: Возможно далеко не всем (хотя кого я обманываю? практически никому) не интересно то, что я здесь пишу,
Да просто не понятно вообще что это, и зачем оно нужно. Мы такие хитроумные конструкции не юзаем
Цитата:
Дядя Миша писал: Раз в 10 медленее, а может быть и в сто.
Ну так же будет возможность скомпилировать его в обычный бинарный код? Например как в Юнити. Можно и ВМ юзать, а можно просто в бинарники собрать.
__________________ Иван Топорышкин пошел на охоту,
С ним пудель пошел, перепрыгнув забор,
Иван, как бревно провалился в болото,
А пудель в реке утонул, как топор.
FiEctro писал: Ну так же будет возможность скомпилировать его в обычный бинарный код?
Нет конечно. Или ты имеешь в виду JIT?
Если что-то можно можно собрать в "обычный бинарный файл", значит все возможности и удобства виртуальной машины идут по звезде.