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

FBX Animation (3 стр)

Страницы: 1 2 3 4 Следующая »
#30
11:54, 3 июня 2016

Osiris
На вашем месте я бы все же задавал систему координат при экспорте. Сразу бы работы поубавилось.

Плагины FBX для автодесковских продуктов это позволяют.


#31
12:03, 3 июня 2016

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

Я сейчас понял, что матрица геометрии содержит часть трансформации самого узла, потому что я поставил единичные матрицы узлом и оставил только трансформацию геометрии, в итоге у меня модель полностью собрана, только не по осям ... дела

#32
12:44, 3 июня 2016

Только geometry transform, только хардкор (только поменял Y и Z трансформацию местами).
ship1 | FBX Animation
Все окей, ось Y вверх - в пакете это вперед, все норм, может быть Х не туда, так как модель зеркальная, не суть.

Добавляю трансформацию узла
ship2 | FBX Animation

Напоминаю, ничего не менял кроме как трансформацию, в случае с матрицей узла что только не пробовал менять - все плохо, и это очевидно что так, потому что в все хранится в геометрии и узел вообще лишний, я нифига не пойму.

#33
14:54, 3 июня 2016

Osiris
Те детали, что поехали, они не отдельными нодами сделаны?

Если отдельными, то надо еще и позицию нодов учитывать, если она отлична от нуля. А если у нодов еще и ориентация не identity, то и ее туда же.

#34
17:00, 3 июня 2016

Barabus
> Если отдельными, то надо еще и позицию нодов учитывать, если она отлична от
> нуля. А если у нодов еще и ориентация не identity, то и ее туда же.
Отдельными. Там где поехала трансформация - там ДОБАВЛЕНА трансформация узла, а где не поехала - там нет, там ТОЛЬКО геометрия. В том и проблема.

#35
19:10, 3 июня 2016

Плюнул пока на трансформации, пытаюсь разобраться с анимацией. У меня вопрос по позам, где их брать, если они никак не описаны в AnimationLayer или AnimationStack?

Нашел, он в сцене ... и как понять с какой анимацией они связаны?

#36
12:51, 4 июня 2016

Да, скелетка еще инетереснее, нашел в примерах:

        double lWeight = lCluster->GetControlPointWeights()[k];

        if (lWeight == 0.0)
        {
          continue;
        }

        // Compute the influence of the link on the vertex.
        FbxAMatrix lInfluence = lVertexTransformMatrix;
        MatrixScale(lInfluence, lWeight);

        if (lClusterMode == FbxCluster::eAdditive)
        {    
          // Multiply with the product of the deformations on the vertex.
          MatrixAddToDiagonal(lInfluence, 1.0 - lWeight);
          lClusterDeformation[lIndex] = lInfluence * lClusterDeformation[lIndex];

          // Set the link to 1.0 just to know this vertex is influenced by a link.
          lClusterWeight[lIndex] = 1.0;
        }
        else // lLinkMode == FbxCluster::eNormalize || lLinkMode == FbxCluster::eTotalOne
        {
          // Add to the sum of the deformations on the vertex.
          MatrixAdd(lClusterDeformation[lIndex], lInfluence);

          // Add to the sum of weights to either normalize or complete the vertex.
          lClusterWeight[lIndex] += lWeight;
        }

MatrixAdd - это сложение ... сложение итоговой матрицы по весам ... это что *** вообще такое?

#37
14:55, 4 июня 2016

> MatrixAdd - это сложение ... сложение итоговой матрицы по весам ... это что *** вообще такое?
Osiris, софтварная скелетка что ли?

Ты чего получить-то хочешь в итоге?

#38
15:56, 4 июня 2016

Osiris
> У меня вопрос по позам, где их брать, если они никак не описаны в
> AnimationLayer или AnimationStack?
Анимация — это не позы, это наборы ключей для каждого анимированного объекта. Каждый ключ — это некоторая величина, привязанная ко времени. К примеру анимация позиции кости — это три кривые, описывающие изменение компонентов X, Y и Z позиции. Каждая кривая — набок ключей, каждый ключ: значение координаты, время и метод интерполяции. С ориентацией и масштабированием — аналогично. Все по аналогии того, как это реализовано в 3D-редакторе.

Матрицы не ищите, их там нет. Их вам придется собрать самостоятельно. Смотрите иерархию объектов в документации.

А участок кода, который вы показываете — это софтварная скелетка, это вам не надо.

#39
15:57, 4 июня 2016

slava_mib
> Ты чего получить-то хочешь в итоге?
Мне матрицы нужны в шейдер, то есть мне аналогично в шейдере сделать обработку. Но в шейдере я перемножаю с учетом веса, а тут вообще сложение, и весов тоже. Я шибко уже жалею, что потратил время на эту либу.

Barabus
>А участок кода, который вы показываете — этософтварная скелетка, это вам не надо.
Ну что же мне нужно брать за образец, потому что сейчас там у меня набор треугольников вовсе стороны.

Я пока без всякой анимации хочу просто с базовой транфсформацией модель поставить. То есть когда все кости в начальном положении.

#40
18:52, 4 июня 2016

> Я шибко уже жалею, что потратил время на эту либу.
Osiris, ФБХ - самое говное говоно из всех либ, что я видел, про уровню хреновости огранизации и бедарности документирования она находится где-то примерноа на одном уровне с Intel Havok. Но прикол в том, что альтернатив этому говну просто нет. Потому либо с ним, и будет боле-мене универсально, либо никак 8-(

Если тебе нужна обычная скелетка, то тут, как и всегда будет два ньюанса - получить бинд-позу и, собственно, замутить саму анимацию. И то и другое достаточно легко гуглится. так же можешь посмотреть (код) в уже готовых решениях, типа, скажем Ozz - там код, конечно, не лучший, но относительно понятный и комментов прям дофига в тех местах, где они реально нужны - потому разобраться будет несложно. Там в либе есть и бинд-позы, и анимации, и меши и т.д. - и всё это в т.ч. с извелением из фбх. Я по этолму коду боле-мене нормально смог подразобраться, даже несмотря на то, что он всё равно не полный (там нет текстурных координат, ТБН-базисов и т.д.) - но что бы разобраться со скелеткой самое то.

Ну и ещё без проблем гуглится 100500 кода типа вот этого: http://www.gamedev.net/topic/658450-fbx-and-skinned-animation/

> Я пока без всякой анимации хочу просто с базовой транфсформацией модель поставить. То есть когда все кости в начальном положении.
Osiris, если в базовой - то тут скелетка вообще не нужна. Надо тогда делать просто загрузку моделей из ФБХ - это, слава богу, можно сделать даже чито по неадекватным докам самой либы (но если есть какие конкретные вопросы - пиши, постараюсь помочь). Я так примерно и делал у себя:
- снчала загрузка просто моделей
- потом скелетов
- потом анимаций
- потом имфа скининга
- а потом уже проигрывание всего этого дела в комплексе

#41
0:27, 5 июня 2016

slava_mib
> про уровню хреновости огранизации и бедарности документирования она находится
> где-то примерноа на одном уровне с Intel Havok

Я подключил Havok Animation за 2 часа к движку) Просто сейчас он не бесплатен.

>Я по этолму коду боле-мене нормально смог подразобраться, даже несмотря на то, что он всё равно не полный (там нет текстурных координат, ТБН-базисов и т.д.) - но что бы разобраться со >скелеткой самое то.

Спасибо, гляну.

>Ну и ещё без проблем гуглится 100500 кода типа вот этого
Ну это я видел, даже помогло на начальном этапе, только в текущих версиях FBX SDK анимация в примерах иначе делается.

>если в базовой - то тут скелетка вообще не нужна.
Как раз таки это скелетка без анмиации, первый этап - загрузка скелета в стартовой позе. Вот на нем сейчас затык. Что мне в итоге надо - я понимаю, но только что хранит FBX - х*й знает.

Видимо свою буду делать, блендинг только нужен будет тоже, с ним вроде как не просто все.

#42
12:21, 5 июня 2016

> Я подключил Havok Animation за 2 часа к движку)
Osiris, это, скорее всего, ты просто недостаточно глубоко копался - может тебе повезло и твои задачи этолго и не требуют. А вот когда начнёшь всякие там блендинги, аддитивные, да ещё с 100500 потоками, и обращениям к костям и т.д. - вот там начнётся ад - он будет сыпать ошибками, падать, кидать эксепшены и т.д. и всё это не будет никак документировано. А пока один поток и минимум действий - всё работает как часы )))

>Просто сейчас он не бесплатен.
Старым пользователям разрешено использовать на старых условиях.

> Как раз таки это скелетка без анмиации, первый этап - загрузка скелета в стартовой позе. Вот на нем сейчас затык. Что мне в итоге надо - я понимаю, но только что хранит FBX - х*й знает.
Osiris, т.е. тебе всё же нужно скелетку, но пока без анимации, чисто для теста бинд-позу? Тогда для начала выгрузи правильно веса костей, построй инверт-бинд-позу (если будет нужен код - свисти), ну а дальше уже в принципе всё просто и обычно -  текущее положение  = поза*инв-бинд, кидаем его в шОйдер, и там по индексам берём из констант или текстуры и трансформим вертексы.

#43
19:31, 5 июня 2016

slava_mib
> Старым пользователям разрешено использовать на старых условиях.
НУ я не для себя сейчас. А так да, я блендинг делал, но простой двух анимаций.

> т.е. тебе всё же нужно скелетку, но пока без анимации, чисто для теста бинд-позу? Тогда для начала выгрузи правильно веса костей, построй инверт-бинд-позу (если будет нужен код - свисти),
Давай я покажу, на всякий пожарный, но вообще уже решил что напишу выгрузку из Х формата пока без бленда.

Итак, вот так вот я вытаскиваю индексы и веса, там в принципе все нормально, походу. Логика - для каждого кластера (а это видимо косточка) мы находим все точки, на которые он действует и записываем индексы и веса, а потом рассовываем по вершинам.

  // for each cluster (bone) we making temporary buffer on each control point to gather data 
  for (iClusterIndex = 0; iClusterIndex < iClusterCount; ++iClusterIndex)
  {
    pCluster = pSkinDeformer->GetCluster(iClusterIndex);
    if (!pCluster->GetLink())
      continue;

    uControlPointIndicesCount= pCluster->GetControlPointIndicesCount();
    for (int k = 0; k < uControlPointIndicesCount; ++k)
    {
      // this is the index of control point
      // index of bone is a iClusterIndex
      uControlPointID = pCluster->GetControlPointIndices()[k];

      // Sometimes, the mesh can have less points than at the time of the skinning
      // because a smooth operator was active when skinning but has been deactivated during export.
      if (uControlPointID >= iControlPointsCount)
        continue;

      dWeight = pCluster->GetControlPointWeights()[k];
      if (dWeight == 0.0)
      {
        continue;
      }

      // store it in temporary buffer
      pIWData = &stdvControlPointsIW[uControlPointID];

      // no more than 4 bones on vertex
      if (pIWData->_24 != 0.0f)
      {
        CLog::Get().Report(LOG_REPORT_TYPE_ERROR, AFStr("%s"),
          AFStr("CFBXMeshManager::ImportMeshStreamSkinningIWFromFBX() : some vertexes has linked transform bones more then 4. \n"));
        return false;
      }

      if (pIWData->_21 == 0.0f)
      {
        pIWData->_11 = (float)iClusterIndex;
        pIWData->_21 = (float)dWeight;

        continue;
      }

      if (pIWData->_22 == 0.0f)
      {
        pIWData->_12 = (float)iClusterIndex;
        pIWData->_22 = (float)dWeight;

        continue;
      }

      if (pIWData->_23 == 0.0f)
      {
        pIWData->_13 = (float)iClusterIndex;
        pIWData->_23 = (float)dWeight;

        continue;
      }

      if (pIWData->_24 == 0.0f)
      {
        pIWData->_14 = (float)iClusterIndex;
        pIWData->_24 = (float)dWeight;

        continue;
      }

    }
  }

  // FILL

  // polygons info
  int iMapping = GetFBXMeshMappingType(pFBXMesh);
  int iPoly = 0, iVetex = 0;

  // for all vertexes in all polygons
  for (int i = 0; i < sVertexesCount; ++i, ++VertexIndeces, ++VertexWeight)
  {
    switch (iMapping)
    {
    case FbxGeometryElement::eByControlPoint:
    {
      // for each control point
      uControlPointID = i;
    }
    break;

    case FbxGeometryElement::eByPolygonVertex:
    {
      // for each vertex in polygon
      assert(sVertexesCount == pFBXMesh->GetPolygonCount() * 3);

      // 3 vertex for poly
      iPoly = i / 3;
      iVetex = i - (i / 3)*3;
      uControlPointID = pFBXMesh->GetPolygonVertex(iPoly, iVetex);
    }
    break;
    }

    // get point
    pIWData = &stdvControlPointsIW[uControlPointID];

    // copy indeces
    VertexIndeces->x = pIWData->_11;
    VertexIndeces->y = pIWData->_12;
    VertexIndeces->z = pIWData->_13;
    VertexIndeces->w = pIWData->_14;

    // copy weights
    VertexWeight->x = pIWData->_21;
    VertexWeight->y = pIWData->_22;
    VertexWeight->z = pIWData->_23;
    VertexWeight->w = pIWData->_24;

  }

А вот так вот я пытаюсь вытащить матрицы стартовой позы (напоминаю что у меня какие-то проблемы с матрицами узлов. но в примере вроде единичная).

  // for each cluster (bone) we making temporary buffer on each control point to gather data 
  for (iClusterIndex = 0; iClusterIndex < iClusterCount; ++iClusterIndex, ++Bones)
  {
    pCluster = pSkinDeformer->GetCluster(iClusterIndex);
    if (!pCluster->GetLink())
      continue;

    ClusterMode = pCluster->GetLinkMode();
    if (ClusterMode == FbxCluster::eAdditive)
    {
      return false;
    }

    if (ClusterMode == FbxCluster::eTotalOne)
    {
    }

    // calculation of transform matrix
    pCluster->GetTransformMatrix(mReferenceGlobalInitPosition);
    mReferenceGeometry = GetGeometry(pFBXMesh->GetNode());
    // now to LH
    if (m_bOptionConvertToLH)
    {
      pTranslation = mReferenceGeometry.GetT();
      //  pRotation = mReferenceGlobalInitPosition.GetR();

      pTranslation.Set(pTranslation.mData[0], pTranslation.mData[2], pTranslation.mData[1]);
      //  pRotation.Set(pRotation.mData[0], pRotation.mData[2], pRotation.mData[1]);

        mReferenceGeometry.SetT(pTranslation);
      //  mReferenceGlobalInitPosition.SetR(pRotation);
    }

    // now to LH
    if (m_bOptionConvertToLH)
    {
      pTranslation = mReferenceGlobalInitPosition.GetT();
      //  pRotation = mReferenceGlobalInitPosition.GetR();

      pTranslation.Set(pTranslation.mData[0], pTranslation.mData[2], pTranslation.mData[1]);
      //  pRotation.Set(pRotation.mData[0], pRotation.mData[2], pRotation.mData[1]);

      mReferenceGlobalInitPosition.SetT(pTranslation);
      //  mReferenceGlobalInitPosition.SetR(pRotation);
    }

    mReferenceGlobalInitPosition *= mReferenceGeometry;

    // Get the link initial global position and the link current global position.
    pCluster->GetTransformLinkMatrix(mBoneGlobalInitPosition);

    // now to LH
    if (m_bOptionConvertToLH)
    {
      pTranslation = mBoneGlobalInitPosition.GetT();
    //  pRotation = mBoneGlobalInitPosition.GetR();

      pTranslation.Set(pTranslation.mData[0], pTranslation.mData[2], pTranslation.mData[1]);
    //  pRotation.Set(pRotation.mData[0], pRotation.mData[2], pRotation.mData[1]);

      mBoneGlobalInitPosition.SetT(pTranslation);
    //  mBoneGlobalInitPosition.SetR(pRotation);
    }

    lClusterGlobalCurrentPosition = GetGlobalPosition(pCluster->GetLink(), 0, pPose, NULL);
    if (m_bOptionConvertToLH)
    {
      pTranslation = lClusterGlobalCurrentPosition.GetT();
      //  pRotation = mBoneGlobalInitPosition.GetR();

      pTranslation.Set(pTranslation.mData[0], pTranslation.mData[2], pTranslation.mData[1]);
      //  pRotation.Set(pRotation.mData[0], pRotation.mData[2], pRotation.mData[1]);

      lClusterGlobalCurrentPosition.SetT(pTranslation);
      //  mBoneGlobalInitPosition.SetR(pRotation);
    }


    // Compute the initial position of the link relative to the reference.
    mBoneTransformInit = lClusterGlobalCurrentPosition.Inverse() * mBoneGlobalInitPosition.Inverse() * mReferenceGlobalInitPosition;
//    mBoneTransformInit = mReferenceGlobalInitPosition * mBoneGlobalInitPosition.Inverse() * lClusterGlobalCurrentPosition.Inverse();

    // to array
    *Bones = GetAFMatrixFromFBX(mBoneTransformInit);
  }

#44
19:32, 5 июня 2016

Вспомогательные функции собраны из примеров

// Get the geometry offset to a node. It is never inherited by the children.
FbxAMatrix GetGeometry(FbxNode* pNode)
{
  const FbxVector4 lT = pNode->GetGeometricTranslation(FbxNode::eSourcePivot);
  const FbxVector4 lR = pNode->GetGeometricRotation(FbxNode::eSourcePivot);
  const FbxVector4 lS = pNode->GetGeometricScaling(FbxNode::eSourcePivot);

  return FbxAMatrix(lT, lR, lS);
}

// Get the matrix of the given pose
FbxAMatrix GetPoseMatrix(FbxPose* pPose, int pNodeIndex)
{
  FbxAMatrix lPoseMatrix;
  FbxMatrix lMatrix = pPose->GetMatrix(pNodeIndex);

  memcpy((double*)lPoseMatrix, (double*)lMatrix, sizeof(lMatrix.mData));

  return lPoseMatrix;
}

//
FbxAMatrix GetGlobalPosition(FbxNode* pNode, const FbxTime& pTime, FbxPose* pPose, FbxAMatrix* pParentGlobalPosition)
{
  FbxAMatrix lGlobalPosition;
  bool        lPositionFound = false;

  if (pPose)
  {
    int lNodeIndex = pPose->Find(pNode);

    if (lNodeIndex > -1)
    {
      // The bind pose is always a global matrix.
      // If we have a rest pose, we need to check if it is
      // stored in global or local space.
      if (pPose->IsBindPose() || !pPose->IsLocalMatrix(lNodeIndex))
      {
        lGlobalPosition = GetPoseMatrix(pPose, lNodeIndex);
      }
      else
      {
        // We have a local matrix, we need to convert it to
        // a global space matrix.
        FbxAMatrix lParentGlobalPosition;

        if (pParentGlobalPosition)
        {
          lParentGlobalPosition = *pParentGlobalPosition;
        }
        else
        {
          if (pNode->GetParent())
          {
            lParentGlobalPosition = GetGlobalPosition(pNode->GetParent(), pTime, pPose, pParentGlobalPosition);
          }
        }

        FbxAMatrix lLocalPosition = GetPoseMatrix(pPose, lNodeIndex);
        lGlobalPosition = lParentGlobalPosition * lLocalPosition;
      }

      lPositionFound = true;
    }
  }

  if (!lPositionFound)
  {
    // There is no pose entry for that node, get the current global position instead.

    // Ideally this would use parent global position and local position to compute the global position.
    // Unfortunately the equation 
    //    lGlobalPosition = pParentGlobalPosition * lLocalPosition
    // does not hold when inheritance type is other than "Parent" (RSrs).
    // To compute the parent rotation and scaling is tricky in the RrSs and Rrs cases.
    lGlobalPosition = pNode->EvaluateGlobalTransform(pTime);
  }

  return lGlobalPosition;
}

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

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