war_zes
> В таком случае надо начинать с core кода (профилирование, логирование, сборка,
> платформа)... Я так сейчас и собираюсь сделать (тож заведу сообщество своего
> движка:) )
Так это замечательно! Движок всем и каждому!
Логирование и обработку ошибок я планирую как раз следующим шагом. Сборка это очень сложный вопрос: кросс-платформенных утилит подготовки проектов для VisualStudio, XCode и Eclipse просто нет. CMake не в счёт, потому как некоторые вещи сделать либо невозможно, либо через очень большую жопу. Но! Если есть супер специалист, который не согласен с этим и может идеально настроить генерацию проектов под выше озвученные IDE - я буду только за.
Ну а платформа уже строится на вышеописанном.
foxes
> vecFunctions.V3ICombine(v1,v2,v3,0.1,100); // v3=v1*0.1+v2*100;
Вот раз уж на то пошло, то хотелось бы писать в коде
v3=v1*0.1+v2*100;
а в итоге чтобы выполнялось
vecFunctions.V3ICombine(v1,v2,v3,0.1,100);
Благо язык это делать позволяет.
IROV..
Добрый.
> http://svn.code.sf.net/p/menge-engine/code/trunk
Работа проделана большая... А есть краткое описание или список фич, примеры? Я посмотрю подробно на выходных исходники.
> могу предложить его за основу и продолжить разработку
Хотелось делать с нуля, просто как упоминалось выше, зачем тогда вообще что-то делать? Ведь есть же Cocos2d-x, например, и ещё куча движков, тот же free Unity - объективно его этот двиг вообще хрен когда догонит по возможностям. Или тот же UnrealEngine - сейчас стал стоить очень демократично, чуть ли не студент его может себе официально позволить. Но если какая-то чужая подсистема хорошо вписывается и если написать самому заново - получится то же самое, то почему бы не позаимствовать с разрешения автора? :)
> ну или чем-то помочь :) есть опыт в любом озвученном в первом посте вопросе
Это всегда велкам! Помощь если не кодом, то хотя бы советом никогда не помешает!
the_siv
> Работа проделана большая... А есть краткое описание или список фич, примеры? Я
> посмотрю подробно на выходных исходники.
Это верхушка айсберга, большая часть работы закопана в Фреймворке написанном на Python, скриптов экспорта из PS и After Effecta, примеры - выпущенные игры)), вообще я исходил из того что всю логику игры мы пишем на питоне и ни строчки на С++
> > могу предложить его за основу и продолжить разработку
> Хотелось делать с нуля, просто как упоминалось выше, зачем тогда вообще что-то
> делать? Ведь есть же Cocos2d-x, например, и ещё куча движков, тот же free Unity
> - объективно его этот двиг вообще хрен когда догонит по возможностям. Или тот
> же UnrealEngine - сейчас стал стоить очень демократично, чуть ли не студент его
> может себе официально позволить. Но если какая-то чужая подсистема хорошо
> вписывается и если написать самому заново - получится то же самое, то почему бы
> не позаимствовать с разрешения автора? :)
Понимаю - но то что выше это ГОДЫ работ :) это нужно понимать
> > ну или чем-то помочь :) есть опыт в любом озвученном в первом посте вопросе
> Это всегда велкам! Помощь если не кодом, то хотя бы советом никогда не
> помешает!
Буду рад помочь :)
the_siv
> Вот раз уж на то пошло, то хотелось бы писать в коде
> v3=v1*0.1+v2*100;
> Благо язык это делать позволяет.
Для этого классы и написаны.
the_siv
> специалист, который не согласен с этим и может идеально настроить генерацию
> проектов под выше озвученные IDE - я буду только за.
qmake + *.pro
Генерит проекты для VisualStudio, XCode и Eclipse и CMake..
Исходник открыт можно настроить под себя, без использования QT.
или указать в pro
CONFIG -= flat qt
QT -= core gui
или переписать mkspecs
IROV..
а сколько времени ты делал свой движок?
и что использовалось в качестве редактора уровней?
(небольшая опечатка в "Utils/Core/IntrusiveSprayTree.h" - spray вместо splay.)
PVSector
> а сколько времени ты делал свой движок?
в соурсфорже он появился в 2006 году, активно(фулл тайм) начал разрабатывать 3-4 года назад
> и что использовалось в качестве редактора уровней?
Photoshop + After Effect + Excel - при любом редакторе для более менее норм игры всегда приходишь к Notepad (это я намекаю на Unity)
> (небольшая опечатка в "Utils/Core/IntrusiveSprayTree.h" - spray вместо splay.)
Упс.. ведь внутри же ссылаюсь на себя же
# include <stdex/intrusive_splay_tree.h>
Но я отказался от него, там шаблонами выключен сам "принцип" из за проблем с многопоточностью
З.Ы. Спасибо, исправил
the_siv
из низкоуровневых вещей вот это можно бы описать:
- кроссплатформенная математика и как нужно конвертировать матрицы при передачи в шейдеры (напр., если движок использует систему координат, отличную от Direct3D / OpenGL );
- система ввода, key binding / input action mapping - translating user input events into game actions;
- multithreaded job/task manager - e.g. dividing frame rendering into tasks and spreading workload among threads;
the_siv
А по поводу "хочется с нуля" в данном движке есть ТОННА не охваченной работы, и разгуляться можно, и как бонус есть где тестировать :)
PVSector
Отвечу что знаю, может что-то IROV ответит. Хорошо бы если бы ещё опытные люди подключились.
>> кроссплатформенная математика
В основном наоборот сложно сделать математику не кросс-платформенной, а вообще могут быть грабли при разработке под 32бита, а использовании под 64бита, ито это только в случае с целыми числами, притом что компилятор покажет ворнинги. Так ещё и скорее всего всё-равно будет работать (но возможны редкие трудно уловимые баги приведения большого 32 битного числа к 64 битному). Ещё могут быть проблемы при чтении из бинарного файла, в который сохраняли Big-endian числа, а читают Little-endian, или наоборот. Но и тут: Big-endian платформы - это эзотерика. Так же проблемы в оптимизации, если вдруг используется ассемблерные вствки и/или сопроцессор. В остальном, если не используется ничего платформо-зависимого, то проблем быть не должно. Но, кстати надо быть аккуратным со стандартной библиотекой, в некоторых ньюансах стандартная библиотека может отличаться у микрософт, gcc и clang (их там, кстати, несколько).
>> как нужно конвертировать матрицы при передачи в шейдеры (напр., если движок использует систему координат, отличную от Direct3D / OpenGL );
тут главный вопрос: зачем движок так поступает? :) вообще говоря не совсем понимаю вопрос, какую такую систему координат можно выдумать? Так или иначе разница будет только в проекционной матрице, ну её собственно можно посчитать по разному в зависимости от графического API, например, оставив это на откуп виртуальной ф-ции рендера. Так же бывает необходимость передавать матрицы в шейдер не в виде 4x4, а в виде 4x3 потому как один столбец (или строка - это как посмотреть) практически для всех матриц, кроме проекционной, всегда оказывается равен (0, 0, 0, 1). И большинство стандартов/версий шейдеров поддерживают работу сразу с матрицами 3x4 (может и все, но с уверенностью не могу сказать), а если и кто-то не поддерживает, то можно привести к виду 4x4 прямо в шейдере. Зачем это делать? Чтобы на 25% увеличить количество костей, например. Либо на те же 25% разгрузить шину.
Ещё есть ньюанс в Matrix-ordering. Надо, чтобы он везде был одинаковый (расчёты в движке и работа с матрицами в шейдерах разных Graphics API).
>> система ввода, key binding / input action mapping - translating user input events into game actions;
Я считаю тут не нужно за ранее усложнять. Для начала обработки "в лоб" вполне достаточно:
void Board::onKeyDown(input::Key key) { if ( key==input::keyUp) { hero->goUp( ); } }
Вот когда это покажется слишком ограниченным и не правильным, тогда и появятся ответы почему это плохо и как надо делать. Потому что требования и задачи у всех разные, в результате решения так же разные получаются: не должна система инпута для FPS и для пасьянса быть одинаковой, несмотря на то, что и там, и там используется мышка для пользовательского ввода.
>> multithreaded job/task manager - e.g. dividing frame rendering into tasks and spreading workload among threads;
Опять же от задачи зависит. Если сделать слишком обобщённо, то и профита может не быть вообще. Даже рендер на отдельный поток посадить, во-первых, не так уж просто, а, во-вторых, профит будет не так велик, как хотелось бы, потому что разработчики самих графических API уже подумали за нас, чтобы фактический рендер максимально происходил в неблокирующем для приложения режиме. Что мне приходилось делать: асинхронные сетевые запросы (задание делается в основном потоке, выполняется в другом, после выполнения в основном потоке вызывается назначенный callback), асинхронное раскодирование видео по подобному принципу, фоновая загрузка ресурсов, воспроизведение музыки в другом потоке. В общем все эти задачи хорошо ложились на систему многопоточности, кроме раскодирования видео - но там если пора рисовать, а кадр ещё не раскодирован - просто ничего не делалось, таким образом избегалась взаимная блокировка потоков.
IROV..
> А по поводу "хочется с нуля" в данном движке есть ТОННА не охваченной работы, и
> разгуляться можно, и как бонус есть где тестировать :)
Для принятия такого важного решения надо досконально изучить движок: плюсы/минусы, что есть/чего нет. Есть описание хоть в каком-то виде? Я не только для себя спрашиваю - если ты утверждаешь, что уже сейчас на нём можно написать полноценную игру, то может кто-то станет уже сейчас использовать твой двиг в том виде как он есть сейчас.
IROV..
> Это верхушка айсберга
Так эта, а чего перестал развивать движок? И почему вдруг возникла идея возобновить работы? И зачем тебе вообще я?
the_siv
> вообще говоря не совсем понимаю вопрос, какую такую систему координат можно
> выдумать?
Очень часто бывает разрыв мозга по поводу различных картографических систем, поскольку не всем понятно что все это является той же геометрией, начинают появляться различного рода теории о существовании вне земных математик. А иногда просто, считая что если вектора системы координат показывают в какие то другие (может быть не перпендикулярные) стороны, то это уже другая математика.
Да кстати, насколько я заметил разница в column-major и row-major только в форме записи в документации, технически значения матрицы хранятся одинаково?
foxes
> Да кстати, насколько я заметил разница в column-major и row-major только в
> форме записи в документации, технически значения матрицы хранятся одинаково.
Вроде как по разному передаются:
Column-major order means that each matrix column will be stored in a single constant register, and row-major order means that each row of the matrix will be stored in a single constant register.
Проще говоря: Column-major = в регистрах хранятся колонки матриц, row-major = в регистрах хранятся ряды матриц.
the_siv
Это относится только к шейдерам? по умолчанию на практике я не замечал чтобы использовались расчеты с транспонированным хранением значений матрицы.
Если переводить на язык системы координат, то применяется хранение {vec4 x;vec4 y;vec4 z;vec4 w;} {vec3 x;vec3 y;vec3 z;} где x,y,z - вектора системы координат (Column-major). Обратного варианта я на практике не встречал: {vec3 Vx;vec3 Vy;vec3 Vz;} где Vn - компоненты векторов системы координат, для z вектора системы координат: {Vx.z,Vy.z,Vz.z}.
Возможно это относится только к внутренним вычислениям не относящимся к хранению матрицы в памяти? Ведь можно считывать как подряд идущие значения (Column-major), так и значения через строку значений (столбец) в регистр (row-major), соответственно вычисления видоизменяются (возможно что упрощаются при умножении вектора на матрицу), а значения в матрице хранятся по старому (Column-major).
foxes
Честно говоря не знаю полного ответа на этот вопрос, есть только догадки. Было бы интересно, если бы кто-нибудь рассказал как оно на самом деле. Моё предположение зачем так делать: например, рассмотрим матрицу трансформаций row-major
11 12 13 14
21 22 23 24
31 32 33 34
41 42 43 44
так вот как правило, не считая проекционных матриц (14, 24, 34, 44) = (0, 0, 0, 1) и не хотелось бы последний столбец вообще пересылать в шейдер, но пересылая такую матрицу через константные регистры, которые float4 получается никакой экономии нет, потому что матрица
r1 (11 12 13)
r2 (21 22 23)
r3 (31 32 33)
r4 (41 42 43)
По прежнему будет занимать 4 регистра. Чтобы матрица занимала 3 регистра можно использовать как раз column-major
r1 (11 21 31 41)
r2 (12 22 32 42)
r3 (33 23 33 43)
Но тут всплывает ньюанс с математикой: как ты справедливо заметил, матрица становится транспонированной и все математические операции следует выполнять имея ввиду этот факт. То-есть либо сразу работать с транспонированными матрицами, либо их преобразовывать при передаче в шейдер. Но если заложить этот факт сразу в основу математической библиотеки и хранить компоненты в column-major, а все расчёты проводить в row-major, то можно передавать в шейдер только первые 12 чисел. И ладно ещё писать такую математическую библиотеку, но потом дебажить это наверное просто ад. Я так никогда не заморачивался, а просто использовал row_major float4x4 mat; но скоро мне понадобится float4x3 - как-то буду паковать...
the_siv
Смысл как раз в том что регистры column-major хранят r1(11 12 13) r2(21 22 23) r3(31 32 33) r4(41 42 43) для записи:
(11 21 31 41)
(12 22 32 42)
(13 23 33 43)
r4 - смещение (translate) (41 42 43)
В то время как row-major r1(11 12 13 14) r2(21 22 23 24) r3(31 32 33 34) для записи:
(11 12 13 14)
(21 22 23 24)
(31 32 33 34)
Здесь смешение разложиться по всем регистрам в последний элемент (14 24 34).
при этом по факту в памяти она будет лежать одинаково для обоих вариантов.
( 0.0 0.1 0.2 0.3 )
( 0.4 0.5 0.6 0.7 )
( 0.8 0.9 1.0 1.1 )
column-major: r1(0.0 0.4 0.8) r2(0.1 0.5 0.9) r3(0.2 0.6 1.0) r4(0.3 0.7 1.1)
vec3 rez=matrix*v; //vec3 rez=r1*v.x+r2*v.y+r3*v.z+r4;
row-major: r1(0.0 0.1 0.2 0.3) r2(0.4 0.5 0.6 0.7) r3(0.8 0.9 1.0 1.1)
vec3 rez=matrix*v; //vec3 rez=vec3(dot(vec4(v,1.0),r1),dot(vec4(v,1.0),r2),dot(vec4(v,1.0),r3));
Соответственно если в шейдере эта особенность автоматом переворачивает расчет (как показано) умножения вектора на матрицу и результат не меняется, то в таком случае логика математической либки (column-major) при стыковки ее с шейдерами не меняется с любой ориентацией в шейдере.
the_siv
> а просто использовал row_major float4x4 mat;
Эта логика обратна той что использует большинство библиотек (включая сам GL) - column-major. Но как я понимаю реально на разницу в передачи данных через Uniform это не влияет. Только если в шейдере не используется ручной поэлементный расчет с матрицами, в место rez=matrix*v;
Ну и если дальше развивать мысль то такие параметры как row_major column_major влияют только на компиляцию математики в шейдере и обращение к элементам в матрице в шейдере, которая не влияет на реальную ориентацию матрицы в памяти. А поскольку при ориентации row_major расчет умножения вектора на матрицу распараллеливается гораздо эффективнее поскольку:
vec3 rez=matrix*v; //vec3 rez=vec3(dot(vec4(v,1.0),r1),dot(vec4(v,1.0),r2),dot(vec4(v,1.0),r3));
Производится 3(4) независимых скалярных умножения. То соответственно ты ее и использовал, что дало более эффективный результат.
Тема в архиве.