Я пытаюсь ответить на ваши вопросы один за другим
- Почему там три скина? Почему inverseBindMatrices связан с кожей, а не с суставом?
Как вы уже узнали, на одну сетку приходится один скин. Тот факт, что в вашем конкретном случае вы можете объединить все три сетки в одну, на самом деле не ограничивает этот общий принцип. Тем не менее
Я думаю, что для каждой сетки должна быть обратная матрица связывания, чтобы можно было преобразовать сетку в костное пространство (и, если необходимо, обратно).
Существует обратная матрица связывания для каждого соединения из каждой сетки . Имя свойства - inverseBindMatrices
во множественном числе по причине, и оно ссылается на bufferview
, которое в свою очередь ссылается на некоторые данные в buffer
.
Здесь меняется порядок вашего вопроса, потому что таким образом это будет иметь больше смысла:
Каждый костный узел в файле имеет свои собственные значения поворота, перемещения и масштаба, но не имеет матрицы. Это почему? Чего-то не хватает?
Что еще тебе нужно? Каждое аффинное преобразование может быть разложено на перевод, вращение и масштабирование, поэтому данные полны. Спецификация glTF определяет, что полученная матрица должна быть вычислена в следующем порядке: T*R*S
.
- Когда у меня есть правильное вращение, масштабирование, перевод из ключевого кадра (на кость), как рассчитать матрицы для каждой кости, которые мне нужно передать в мой вершинный шейдер?
Для каждого костного узла i
вы можете рассчитать локальное преобразование как M_local(i) = T(i)*R(i)*S(i)
. Вы получите объединенные матрицы, применяя полную иерархию, поэтому в основном M_global(i) = M_global(parent(i)) * M_local(i)
, а затем можете построить матрицы объединения как M_joint(i) = inverse(globalTransform) * M_global(i) * inverseBindMatrix(i)
.
- Файл gltf ссылается на кость (сустав) как идентификатор узла, но массивы weights / jointId-Array, которые передаются в качестве атрибутов шейдеру, не соответствуют этим идентификаторам костей: jointIds-Array содержит, например, 0,1,2 для идентификаторов костей, но кости находятся в узлах 4,5,6 - как найти правильную кость для каждого соединения, переданного в шейдер?
Массив jointIds
содержит ссылки на суставы, а не кости (отсюда и название). Скининговый шейдер вообще не заботится о костях, все, что делают кости, - это определяет иерархию суставов, поэтому они влияют на действительные значения M_global
и, следовательно, также M_joint
матриц. i
-я запись просто ссылается на i
-й сустав в массиве joints
соответствующего скина, поэтому ей нужно M_joint(i)
.
- Поскольку каждый скин имеет список из трех (или не более 4) соединений, это соединения, из которых необходимо передать заключительные преобразования в вершинный шейдер.
Почему бы skin
быть ограничено 4 суставами. Кожа может иметь столько суставов, сколько ей нравится.
Если у вас есть 8 суставов, но на текущую сетку, на которую нужно нарисовать, влияют только 4 из них, почему вы должны пропустить все 8 матриц, а не только 4, которые вам нужны.
Зачем вам определять шкуру из 8 костей для меша, которому нужно только четыре? Формат данных glTF не мешает вам хранить нерелевантную информацию или хранить информацию неэффективным способом.
Здесь следует отметить, что иерархия между суставами все еще определяется иерархией костного узла skeleton
. Таким образом, вы можете исключить произвольные суставы в одном skin
, но эти костные узлы (и потенциальная анимация для них) могут по-прежнему влиять на конечные матрицы суставов - для любого сустава, определяемого костью, которая находится ниже «пропущенных» костей. в иерархии костей скелета.