Войти
ПрограммированиеФорумГрафика

FBX Animation

Страницы: 1 2 3 4 Следующая »
#0
17:34, 28 мая 2016

Подкиньте идей, я делаю экспорт из FBX формата, проблемы с текстурными координатами. На боксе все окей, но если брать модели сложнее, то ползут текстурные координаты
Vertexes

  case FbxGeometryElement::eByPolygonVertex:
  {
    assert(sVertexesCount == pFBXMesh->GetPolygonCount() * 3);
    // for each
    int iControlPoint = 0;
    int lPolySize = 0;

    for (size_t i = 0; i < pFBXMesh->GetPolygonCount(); ++i)
    {
      lPolySize = pFBXMesh->GetPolygonSize(i);
      if (lPolySize != 3)
        return false;

      iControlPoint = pFBXMesh->GetPolygonVertex(i, 0);
      Point = pFBXMesh->GetControlPointAt(iControlPoint);

      pVertexes->x = static_cast<float>(Point.mData[0]);
      pVertexes->y = static_cast<float>(Point.mData[1]);
      pVertexes->z = static_cast<float>(Point.mData[2]);
      ++pVertexes;

      iControlPoint = pFBXMesh->GetPolygonVertex(i, 1);
      Point = pFBXMesh->GetControlPointAt(iControlPoint);

      pVertexes->x = static_cast<float>(Point.mData[0]);
      pVertexes->y = static_cast<float>(Point.mData[1]);
      pVertexes->z = static_cast<float>(Point.mData[2]);
      ++pVertexes;

      iControlPoint = pFBXMesh->GetPolygonVertex(i, 2);
      Point = pFBXMesh->GetControlPointAt(iControlPoint);

      pVertexes->x = static_cast<float>(Point.mData[0]);
      pVertexes->y = static_cast<float>(Point.mData[1]);
      pVertexes->z = static_cast<float>(Point.mData[2]);
      ++pVertexes;

    }
  }

UVs

    case FbxGeometryElement::eIndexToDirect:
    {
      int iUVsCount = VertexUVs->GetIndexArray().GetCount();
      assert(sTrianglesCount * 3 == iUVsCount);

      int index = 0;

      for (size_t i = 0; i < sTrianglesCount; ++i)
      {
        lPolySize = pFBXMesh->GetPolygonSize(i);
        if (lPolySize != 3)
          return false;

        index = pFBXMesh->GetTextureUVIndex(i, 0);
        // this is UV for poly
        UV = VertexUVs->GetDirectArray().GetAt(index);

        pUV->x = static_cast<float>(UV.mData[0]);
        pUV->y = static_cast<float>(UV.mData[1]);
        pUV->x = m_bMirrorU ? 1.0f - pUV->x : pUV->x;
        pUV->y = m_bMirrorV ? 1.0f - pUV->y : pUV->y;
        ++pUV;

        index = pFBXMesh->GetTextureUVIndex(i, 1);
        // this is UV for poly
        UV = VertexUVs->GetDirectArray().GetAt(index);

        pUV->x = static_cast<float>(UV.mData[0]);
        pUV->y = static_cast<float>(UV.mData[1]);
        pUV->x = m_bMirrorU ? 1.0f - pUV->x : pUV->x;
        pUV->y = m_bMirrorV ? 1.0f - pUV->y : pUV->y;
        ++pUV;

        index = pFBXMesh->GetTextureUVIndex(i, 2);
        // this is UV for poly
        UV = VertexUVs->GetDirectArray().GetAt(index);

        pUV->x = static_cast<float>(UV.mData[0]);
        pUV->y = static_cast<float>(UV.mData[1]);
        pUV->x = m_bMirrorU ? 1.0f - pUV->x : pUV->x;
        pUV->y = m_bMirrorV ? 1.0f - pUV->y : pUV->y;
        ++pUV;

      }

Как всегда модель в маппинге Polygons и для UV хранится через IndexArray. Может быть проблема в индексном буфере, я его просто из полигонов собираю

  case FbxGeometryElement::eByPolygonVertex:
  {
    // some vertexes has same position but different normals and other data
    for (size_t i = 0; i < sTrianglesCount; ++i)
    {
      if (pIndexes16)
      {
        *pIndexes16 = (int16_t)(i * 3 + 0);
        ++pIndexes16;

        *pIndexes16 = (int16_t)(i * 3 + 1);
        ++pIndexes16;

        *pIndexes16 = (int16_t)(i * 3 + 2);
        ++pIndexes16;
      }

      if (pIndexes32)
      {
        *pIndexes32 = (int32_t)(i * 3 + 0);
        ++pIndexes32;

        *pIndexes32 = (int32_t)(i * 3 + 1);
        ++pIndexes32;

        *pIndexes32 = (int32_t)(i * 3 + 2);
        ++pIndexes32;
      }
    }

  }

Тут много людей делали, видимо, может что-то очевидное не так? Я уже не соображаю.


#1
22:53, 28 мая 2016

Osiris
> экспорт из FBX формата
Импорт из FBX, наверно?
> assert(sVertexesCount == pFBXMesh->GetPolygonCount() * 3);
Зачем это? Число вершин редко соответствует числу индексов.

> for (size_t i = 0; i < pFBXMesh->GetPolygonCount(); ++i)
Не так. Вам надо покомпонентно дернуть все атрибуты и собрать вершинный буфер на базе контролпойнтов, а не на базе полигонов.

Создаете цикл:

for (size_t i = 0; i < pMesh->GetControlPointsCount(); i++)
{
...
}
Те компоненты, что direct просто дергаете вместе с контролпойттами через GetDirectArray().
Те, что index to direct дергаются уже через GetIndexArray(), а уже на базе этого индексного массива дергаете значения из direct array через GetDirectArray().GetAt().

Я особо не изучал, но вроде как текстурные координаты вы дергаете правильно, но неправильно выбрали базу. Поехало все у вас из-за того, что вы изначально неверно сделали цикл.

Ну а индексный буфер стройте из полигонов, а не генерируйте.

#2
12:01, 29 мая 2016

Barabus
>Импорт из FBX, наверно?
Именно

> Не так. Вам надо покомпонентно дернуть все атрибуты и собрать вершинный буфер
> на базе контролпойнтов, а не на базе полигонов.

Дело в том, что модель хранится именно как
FbxGeometryElement::eByPolygonVertex, а не как FbxGeometryElement::eByControlPoint и в это случае у нас на каждый полигон свои нормали, я не могу использовать скажем 8 вершин на куб и 24 нормали, мне приходится брать 24 вершины - использовать несколько раз.

>Ну а индексный буфер стройте из полигонов, а не генерируйте.
А это как? Я же придерживаюсь логики именно того, что мы обходим полигоны один за другим, для каждого полигона вершины уникальны и расположены последовательно, выходит индексный буфер просто перечисление вершин. Сама модель отображается геометрически верно, но видимо в логике что-то не так, как вы заметили. И все же я не могу брать ControlPoints как основу перебора, ибо полигоны в приоритете.

#3
13:43, 29 мая 2016

Сделал уникальный куб (каждый сторона с уникальной геометрией), на кубе текстурные координаты тоже не так лежат, кроме того видимо индексы не верные.

#4
14:42, 29 мая 2016

В общем модель как-то вывернута. Вот макс, угол обзора уникален, другого сочетания углов такого нет
max | FBX Animation

А вот в проге
pix | FBX Animation

Как будто отзеркалены координаты, бывает такое?

#5
16:04, 29 мая 2016

Osiris
> FbxGeometryElement::eByPolygonVertex
А, понятно. В SDK есть пример. Можете глянуть.

> А это как?
Полигоны по сути группы индексов вершин. Если полигоны — не треугольники, то модель надо предварительно триангулировать либо при экспорте (в максовском экспортере есть такая галочка), либо при импорте (в SDK есть такая функция).

А после просто заполняете ими индексный буфер.

> В общем модель как-то вывернута.
В максе система координат right handed Z-up. Если вы рисуете ее в DirectX, то там left handed Y-up. Это опять же нужно либо явно задавать при экспорте, либо править оси и порядок (CCW to CW) индексов в полигонах при импорте.

#6
17:07, 29 мая 2016

Barabus
> В максе система координат right handed Z-up. Если вы рисуете ее в DirectX, то
> там left handed Y-up. Это опять же нужно либо явно задавать при экспорте, либо
> править оси и порядок (CCW to CW) индексов в полигонах при импорте.

Да, проблема была именно в том, я делал Convert сцены при загрузке, но он не работал. Трансформировал вершины и все нормально, индексы кстати у меня корректные.

#7
18:41, 29 мая 2016

Osiris
> индексы кстати у меня корректные.
Индексы корректные, а число вершин избыточное. Сетка занимает больше места, чем могла бы.

#8
20:23, 29 мая 2016

Barabus
> Индексы корректные, а число вершин избыточное. Сетка занимает больше места, чем
> могла бы.
100% согласен, варианты? У меня нормалей ровно по полигонам, то есть одна вершина для бокса - это 3 полигона, 3 нормали, 3 текстурные координаты.

#9
21:40, 29 мая 2016

Osiris
> 100% согласен, варианты?
Зависит от того, как хранятся компоненты. Если везде для компонентов FbxGeometryElement::eByPolygonVertex, то только так, как вы делаете, а после ручками оптимизировать. Или поискать соответствующую функцию в SDK, если она есть.

#10
22:07, 29 мая 2016

У меня что-то такое (вырезал всё лишнее):

  FbxStringList listUVNames;
  mesh->GetUVSetNames(listUVNames);
  const FbxGeometryElementUV * lUVElement = mesh->GetElementUV(0);
  FbxGeometryElement::EMappingMode lUVMappingMode = lUVElement->GetMappingMode();
  for (int i=0; i<polyCount; i++)
  {
    for (int v=0; v<numVerts; v++, vertexID++)
    {
      int tcIdx = mesh->GetTextureUVIndex(i, v);
      int lUVIndex = tcIdx;
      if (lUVElement->GetReferenceMode() == FbxLayerElement::eIndexToDirect)
      {
        lUVIndex = lUVElement->GetIndexArray().GetAt(tcIdx);
      }
      FbxVector2 lCurrentUV = lUVElement->GetDirectArray().GetAt(lUVIndex);

#11
22:35, 29 мая 2016

slava_mib
> У меня что-то такое (вырезал всё лишнее):
Аналогично, спасибо, уже разобрался с координатами. А что с индексами делаешь? Так же по полигонов создаешь?

#12
2:21, 30 мая 2016

> А что с индексами делаешь? Так же по полигонов создаешь?
Osiris, не понял вопрос 8-(

#13
12:13, 30 мая 2016

slava_mib
> Osiris, не понял вопрос 8-(
Смотри, у нас есть куб, 8 вершин, 16 полигонов, на каждый полигон у нас свои нормали, следовательно по сути у нас 16 * 3 = 48 вершин в буфере. FBX файл так и хранит это для нормалей, текстур и прочего и и видимо не оптимально. Ты как-то с этим боролся?

#14
12:02, 31 мая 2016

Дошел до скелетной анимации, вопрос. Должен ли я матрицы костей переводить из RH в LH?

Страницы: 1 2 3 4 Следующая »
ПрограммированиеФорумГрафика

Тема в архиве.