Войти
Уголок tool-программФорум

Нюансы при экспорте из 3DS MAX (комментарии) (2 стр)

Страницы: 1 2 3 Следующая »
#15
18:24, 22 янв. 2007

Hax брет какой а... это вобще из другой оперы...


#16
11:35, 23 янв. 2007

>Hax брет какой а... это вобще из другой оперы...
Очевидно, вы еще не сталкивались с этой проблемой.
tangent space vectors в вершинах (normal, tangent, binormal) должны быть такими, какие использовались при рассчете normals maps. Если посчитать normal maps, а потом использовать с tagent space vectors, рассчитанными другим алгоритмом - появляются отчетливо видимые стыки и искривления.

Собственно непонятно, как использовать normal maps, посчитанные в 3ds max/maya/zbrush, если неизвестно, какие там tanget space vectors.

#17
18:36, 23 янв. 2007

Hax
Ещё раз... медленно... это вобще из другой оперы...
Разговор шел о экспорте нормалей. Это геометрический уровень. Пиксельные методы тут непричем. Совершенно.

Если очень хочется поговорить про tangent, binormal и normals maps, то tangent и binormal расчитываются для каждой вершини от нормали и текстурных координат карты нормалей. Тоесть нормаль является частью исходных данных но никак не результатом расчетов. Нормаль просто есть, такая какую создал художник. Точно так же как есть позиция вершины в пространстве и есть текстурные координаты. Ведь что такое тангент спейс по сути? Это матрицы 3х3 для каждой вершины, используя которые можно преобразовать вектор из пространства нормаль карты в пространство объекта, и мне кажется вполне логичным что вектор нормаль карты направленный вверх должен после преобразования перейти в вектор равный нормали в данной точке. Мне честно говоря всё равно как 3ds MAX и другое редакторы расчитывают нормаль карты, потому что я использую свой плагин. А Вам, стоит изменится чему то в алгоритмах той же ATI, придется подгонять свой экспортер под эти изменения. А они ведь могут быть недокументированы. Естественно что алгоритм расчета тангент спейса в генераторе нормаль карт и экспортере должен быть идентичен, и добится идентичности какраз проще всего используя свои утилиты, которые работают с УЖЕ экспортированной геометрией, или используют алгоритмы идентичные экспортеру.

#18
12:08, 24 янв. 2007

Мы взяли ATI Normal mapper, т.к. :
1) художники сказали, что он их полностью устраивает;
2) он поставляется в исходниках;
3) писать свой normal mapper особого желания не было.

> или используют алгоритмы идентичные экспортеру.
Как раз это мы и делаем. Для ATI Normal mapper есть свой экспортер в формат NMF. Так вот, этот экспортер нормали пересчитывает. Поэтому наш экспортер  в наш формат нормали тоже пересчитывает. Алгоритм взят из исходников NMFExport.

> А Вам, стоит изменится чему то в алгоритмах той же ATI, придется подгонять свой экспортер под эти изменения.
Точно с такой же вероятностью может измениться класс RNormal :)

#19
14:32, 24 янв. 2007

Интерфейсы меняются реже(в идеале только расширяются) чем реализации...

#20
15:44, 17 фев. 2007

MO
А ты проверял что на эти r-normals действует модификатор EditNormals? Я чё-то как нормали не кручу, одни и те же цифры выдаёт... Действуют только smooth группы. (скопировал твой код практически 1:1)

// вот такую клёвую функцию утащил с http://www.gamedev.ru/community/toolcorner/forum/?id=1149&page=1
Point3* MeshGetVertexNormal(Mesh* mesh, int faceNo, DWORD faceVertV0)
{
  Face* f = &mesh->faces[faceNo];
  DWORD smGroup = f->smGroup;
  int numNormals;
  Point3 *vertexNormal = new Point3;  
  *vertexNormal = mesh->getNormal(f->v[faceVertV0]);
  RVertex* rv = &mesh->getRVert(f->v[faceVertV0]);
  //RVertex *rv = mesh->getRVert(Faces[f].v[i]);
  if(rv->ern)
  {
    for(unsigned int n = 0; n<(rv->rFlags&NORCT_MASK); n++)
      if(rv->ern[n].getSmGroup() == f->smGroup)
      {
        *vertexNormal=rv->ern[n].getNormal();
        break;
      };
  };
  return vertexNormal;
};

имхо для Edit Normals надо юзать функции интерфейса этого модификатора (enfn_get_normal, enfn_get_num_normals etc)

Прошло более 2 лет
#21
19:40, 24 апр. 2009

а я где-то выдрал вот этот код, и теперь похоже из за него поимел проблемы на голову

    Point3    v;
    Point3    n;

    int smGroup = MaxMesh->faces[i].getSmGroup();

    for(int j=0; j<3; j++)
    {
      int vi  = MaxMesh->faces[i].v[j];

      v = MaxMesh->verts[vi];

      if(smGroup != 0)
      {
        n = MaxMesh->getRVertPtr(vi)->rn.getNormal();
      }
      else
      {
        n = MaxMesh->getNormal(vi)/* * ntm*/;
      }
      n = n.Normalize();

народ!!!!! где искать правильный экспорт нормалей??????

я тут 3 дня мучаюсь.....
а тут смотрю в свой экспортер, обычный  параллелепипед, его нормали, а там такой бред:

Normals =
              0              -1              0
              0              -1              0
              0              -1              0
              0              -1              0
              0              1              0
              0              1              0
              0              1              0
              0              1              0

#22
13:43, 12 мая 2009

Исправление к коду MO

  DWORD smGroup = f->smGroup;
  Point3 *vertexNormal = new Point3; 
  *vertexNormal = mesh->getFaceNormal(faceNo);
  if(smGroup==0)
  return vertexNormal;

  RVertex* rv = mesh->getRVertPtr(f->v[faceVertV0]);

Тогда правильно экспортируются нормали для плоских поверхностей.

#23
14:57, 12 мая 2009

Festern
там еще большой вопрос что вызывать, когда нет группы сглаживания

MaxMesh->getFaceNormal(fi);
или
MaxMesh->getNormal(vi);

в обоих случаях есть артефакты.
я так до сих пор и не понял и нигде нету инфы

#24
16:06, 13 мая 2009

getFaceNormal()  было бы логично потому что если нормаль ни с чем не сглаживается, она равномерно-одинакова
по всему треугольнику. Так же считают в Valve Software судя по исходникам их экспортера.
Это не избавляет от всех косяков, но уменьшает их количество=)

А артифакты есть и во вьювпорте максы, особенно при использовании DxShaderMaterial

В 2009й максе появился совсем непонятный глюк с нормалями в окне просмотра. К счастью нечастый.
Смотришь - всё сшито, smooth-группа одна, поверхность ровная, но угол одного из треугольников черный.
(в смысле освещается неправильно, нормаль не в ту сторону).

Кстати, как добраться до модификатора EditNormals (довольно полезный для лоуполи и чамферинга)?

#25
19:21, 13 мая 2009

Вот конечный вариант функции получения нормали.
Думаю, её стоит добавить в статью.

#include "MeshNormalSpec.h"

Point3 MeshGetVertexNormal(Mesh* mesh, int faceNo, DWORD faceVertV0)
{

  //EditNormals modifier
  MeshNormalSpec* specifiedNormals = mesh->GetSpecifiedNormals();
  if( specifiedNormals)
  {
    int normalID = specifiedNormals->GetNormalIndex(faceNo, faceVertV0);
    if( specifiedNormals->GetNormalExplicit( normalID ) )
      return specifiedNormals->GetNormal(faceNo, faceVertV0);
  }

  Face* f = &mesh->faces[faceNo];

  if(f->smGroup==0)
    return mesh->getFaceNormal(faceNo);

  RVertex* rv = mesh->getRVertPtr(f->v[faceVertV0]);

  if(rv->ern)
  {
    for(unsigned int n = 0; n<(rv->rFlags&NORCT_MASK); n++)
    {
      if(rv->ern[n].getSmGroup() & f->smGroup)
      {
        return rv->ern[n].getNormal();
      };
    }
  }
  return rv->rn.getNormal();
};


Проблемы были в

if(rv->ern[n].getSmGroup() & f->smGroup)

и

if(f->smGroup==0)
  return mesh->getFaceNormal(faceNo);

#26
23:26, 15 мая 2009

Festern

а у меня при MaxMesh->getFaceNormal(fi) освещение становится размазанным как бы. т.е. как бы контраст пропадает и я думаю это не просто так.
потому как далеко не всегда нормаль вершин полика = нормаль полика, причем групп сглаживания там нет.
т.е. три нормали полика не всегда параллельны и это нормальная ситуация я уверен.

а с одной нормалью на 3 вершины начинают сильно выделятся отдельные полики и не происходит интерполяции освещения.

так что как хотите а я экпорчу нормаль вершины :)

#27
17:40, 16 мая 2009

Festern
к тому же у тя там ошибко похоже

    MeshNormalSpec* specifiedNormals = MaxMesh->GetSpecifiedNormals();
    if(specifiedNormals)
    {
      int normalID = specifiedNormals->GetNormalIndex(fi, crni); // может вернуть -1
      if(normalID!=-1 && specifiedNormals->GetNormalExplicit(normalID))
      {
        return specifiedNormals->GetNormal(fi, crni);
      }
    }

#28
23:20, 16 мая 2009

Festern
кста , а faceVertV0 это  индекс угла? т.е. 0,1 или 2?

#29
14:12, 19 мая 2009

Да.

Как хочешь, экспорть=) Просто для справки как считаются нормали: сначала считаются нормали для полигонов,
т.е. как раз параллельные для каждой вершины полигона, потом сглаживаются нормали в каждой вершине для
всех полигонов, которым принадлежит эта вершина если их smgroup равны. smgroup причем у одного полигона
может быть и не одна, поэтому они записываются битами в 32х битном слове и сравниваются логическим и (&)
Тоесть если у полигона нет smgroup то он ни с кем не сглаживается и его нормали остаются параллельными.
У тебя в максе точно всё сшито и сглажено? Цель экспортера - добиться точной копии с картинкой во вьювпорте.

Про ошибку спасибо, -1 ещё ни разу не возвращал, но мало ли...

Вот код из smd-экспортера кстати...

    DWORD  smGroupFace  = pface->getSmGroup();

    // Get the 3 RVertex's for this face
    // NOTE: I'm using getRVertPtr instead of getRVert to work around a 3DSMax bug
    RVertex *prvertex0 = pmesh->getRVertPtr(iVertex0);
    RVertex *prvertex1 = pmesh->getRVertPtr(iVertex1);
    RVertex *prvertex2 = pmesh->getRVertPtr(iVertex2);
    
    // Find appropriate normals for each RVertex
    // A vertex can be part of multiple faces, so the "smoothing group"
    // is used to locate the normal for this face's use of the vertex.
    Point3 pt3Vertex0Normal;
    Point3 pt3Vertex1Normal;
    Point3 pt3Vertex2Normal;
    if (smGroupFace) 
    {
      pt3Vertex0Normal = Pt3GetRVertexNormal(prvertex0, smGroupFace);
      pt3Vertex1Normal = Pt3GetRVertexNormal(prvertex1, smGroupFace);
      pt3Vertex2Normal = Pt3GetRVertexNormal(prvertex2, smGroupFace);
    }
    else 
    {
      pt3Vertex0Normal = pmesh->getFaceNormal( iFace );
      pt3Vertex1Normal = pmesh->getFaceNormal( iFace );
      pt3Vertex2Normal = pmesh->getFaceNormal( iFace );
    }
    ASSERT_AND_ABORT( Length( pt3Vertex0Normal ) <= 1.1, "bogus orig normal 0" );
    ASSERT_AND_ABORT( Length( pt3Vertex1Normal ) <= 1.1, "bogus orig normal 1" );
    ASSERT_AND_ABORT( Length( pt3Vertex2Normal ) <= 1.1, "bogus orig normal 2" );
  

функция Pt3GetRVertexNormal

Point3 DumpModelTEP::Pt3GetRVertexNormal(RVertex *prvertex, DWORD smGroupFace)
{
  // Lookup the appropriate vertex normal, based on smoothing group.
  int cNormals = prvertex->rFlags & NORCT_MASK;

  ASSERT_MBOX((cNormals == 1 && prvertex->ern == NULL) ||
        (cNormals > 1 && prvertex->ern != NULL), "BOGUS RVERTEX");
  
  if (cNormals == 1)
    return prvertex->rn.getNormal();
  else
  {
    for (int irn = 0; irn < cNormals; irn++)
      if (prvertex->ern[irn].getSmGroup() & smGroupFace)
        break;

    if (irn >= cNormals) 
    {
      irn = 0;
      // ASSERT_MBOX(irn < cNormals, "unknown smoothing group\n");
    }
    return prvertex->ern[irn].getNormal();
  }
}

Страницы: 1 2 3 Следующая »
Уголок tool-программФорум

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