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

помогите научится работать с форматом .3ds

Страницы: 1 2 Следующая »
#0
16:01, 25 сен. 2006

Вот такая проблема: нужно считать из файла формата .3ds нужную информацию, а именно:
1.  количество вершин объекта и их координаты
2.  количество граней объекта и связь каждой с найденными вершинами.
Перелопатив небольшую кучку информации, стало ясно, что для этого нужно пройти последовательно по чангам:

const CHUNK_MAIN                = 0x4D4D; // [-] сцена
  const CHUNK_OBJMESH           = 0x3D3D; // [-] всяческие объекты
    const CHUNK_OBJBLOCK        = 0x4000; // [+] объект
      const CHUNK_TRIMESH       = 0x4100; // [-] trimesh-объект
        const CHUNK_VERTLIST    = 0x4110; // [+] список вершин
        const CHUNK_FACELIST    = 0x4120; // [+] список граней
и последние два – то, что нужно. Наверное я где-то туплю (впрочем, это почти наверняка),
но экспортировав в нужный формат простой куб с 8-ю вершинами и 12-ю гранями из файла извлекаются просто дурацкие числа. Причем, вершин получается нужное число (если без текстурных координат), а вот треугольников… целых 207. Может что-то с типами у меня не так…

Вот фрагмент кода:

unsigned short chunk = 0;//Идентификатор блока
unsigned int chunk_len = 0;//Смещение к следующему блоку (от chunk_id)

  . . .  /*тут переходы по нужным чангам*/

  while (chunk != CHUNK_VERTLIST) 
  {
    fread((char*)&chunk,2,1, fl);
    fread((char*)&chunk_len,4, 1, fl);  //длина
  }
  pos = ftell(fl);

  int nVertex = 0;
  fread(&nVertex, 1, 1, fl);
  
POINT3D points[MAX_NUM_TRIAN * 3];
  float x, y, z;
  for (int j = 0; j < nVertex; j++)
  {
    fread(&x, 4, 1, fl);
    fread(&z, 4, 1, fl);
    fread(&y, 4, 1, fl);
    points[j].X_PushValue(x);
    points[j].Y_PushValue(y);
    points[j].Z_PushValue(z);
  }

  fseek(fl, pos, SEEK_SET );
  //_______________________считываем грани(треугольники)_______________________
  while (chunk != CHUNK_FACELIST) 
  {
    fread((char*)&chunk,2,1, fl);
    fread((char*)&chunk_len,4, 1, fl);  //длина
  }
  pos = ftell(fl);
  
  int nTriangles = 0;
  fread(&nTriangles, 1, 1, fl);
  TRIANGLE3D triangles[MAX_NUM_TRIAN];
  int p1, p2, p3;
  POINT3D point;
  for (int j = 0; j < nTriangles; j++)
  {
    fread(&p1, 2, 1, fl);
    fread(&p2, 2, 1, fl);
    fread(&p3, 2, 1, fl);
    point = points[p1];
    triangles[j].Point1_PushValue(points[p1]);
    point = points[p2];
    triangles[j].Point2_PushValue(points[p2]);
    point = points[p3];
    triangles[j].Point3_PushValue(points[p3]);
    fread(&p1, 2, 1, fl);  //пропускаем флаги
  }
Собственно, вопрос: в каком месте я треугольники считываю не так.
Заранее сорри за тупой вопрос… просто сидеть в одиночестве и кодить я больше не могу, хотя надо бы…


#1
16:44, 25 сен. 2006

fread((char*)&chunk,2,1, fl);
    fread((char*)&chunk_len,4, 1, fl);  //длина

Я бы сделал так:
fread((char*)&chunk,1,2, fl);
fread((char*)&chunk_len,1, 4, fl);  //длина

и fread(&nTriangles, 1, 1, fl); не уверен что там всего 1байт...
попробуй fread(&nTriangles, 1, кол-во байт, fl);

#2
20:26, 25 сен. 2006

vinny786
Тебе прямая дорога в Focus On 3D Models.
Можно скачать много где с исходниками.

#3
14:37, 28 сен. 2006

VileDog
и fread(&nTriangles, 1, 1, fl); не уверен что там всего 1байт..
если 2  - то то же самое

Я бы сделал так:
fread((char*)&chunk,1,2, fl);
fread((char*)&chunk_len,1, 4, fl);  //длина

так на втором месте же количество считываемых блоков....

#4
14:38, 28 сен. 2006

rAvEn
а что это такое и с чем его едят?

#5
17:11, 29 сен. 2006

кто-нибудь знает точно ли в .3ds формате есть блок CHUCK_OBJMESH = = 0x3D3D
Просто никак моя прога его обнаружить не может (конечно, может дело в моем коде, но все-таки)

#6
20:26, 29 сен. 2006

vinny786
Книжка такая с исходниками.
Там про 3DS и другие все есть и с примерами.

#7
14:00, 30 сен. 2006

Здравствуйте.. Допущенна одна неточность... Странно что с ней все сталкиваются.. :)
Пропущен один чанк у тебя.. а именно


VERSIONF=0x0002  //Информация о версии файла
которая стразу идет за первым главным чанком... после нее уже идет чанк 0x3D3D

Поэтому смещение на чанк мешей гдето 14.. посмотри в хекс редакторе.


Удачи...

#8
18:49, 30 сен. 2006

BlackKite
Спасибо, попробую....

Вопрос пока открыт......

#9
20:59, 30 сен. 2006

Вопрос о количестве граней снят: удалось более-менее нормально найти нужные чанки и т.д.
Кстати, чанка CHUCK_OBJMESH там так и не нашлось, хотя код написан уже совершенно тупо (в смысле ясно), но его там нет.

Чанк VERSIONF есть, спасибо BlackKite, но проблемы это не решает

Возник немного логический вопрос... В доках (не буду делать ссылку на автора) имеется следующее:

Блок: 
 CHUNK_VERTLIST  
Данные: 
 список вершин текущего объекта  
Формат: 
 word num;             // число вершин
vector vertices[num]; // координаты каждой из вершин
 

Блок: 
 CHUNK_FACELIST  
Данные: 
 список граней текущего объекта  
Формат: 
 word num;     // число граней
struct {      //
  word v0;    // номер первой вершины грани
  word v1;    // номер второй вершины грани
  word v2;    // номер третьей вершины грани
  word flags; // флаги грани
} faces[num]; // собственно список граней

Вопрос: что значит номер такой-то вершины?
Если имеется ввиду номер, т.е. индекс нужной вершины в vertiсes, то этого не может быть, так как при отладке считываестся число (тип int) намного большее чем num, буквально для первой грани:

vertices[0]:
  v0 = 131072  (или 0x00020000)
  v1 = 393219  (или 0x00060003)
  v2 = 65539  (или 0x00010003)
Так может это адрес в файле, но это нелогично.

Знающие люди, объясните каким обазом мне перестать тормозить...

#10
19:18, 1 окт. 2006

Обрати внимание на тип данных. В файле пишется unsigned short (2 байта), а ты читаешь int (4 байта). Даже на hex-дампе видно, что там индексы на самом деле 0x002, 0x0000, 0x0006, 0x0003 и т.д.

#11
19:28, 1 окт. 2006

vinny786
Выровняй свои структуры по одному байту т.е.

#pragma pack(push, packing)
#pragma pack(1)

struct sMD2_Vertex
{
          unsigned char v[3];
};

#pragma pack(pop,packing)

иначе код типа

sMD2_Vertex vertex;
fread(&vertex,sizeof(vertex),1,file_in);

может неправильно работать.

#12
20:36, 1 окт. 2006

emage
Ты прав! Чего-то мне подумалось, что не в этом дело... А стоило изменить - и все стало нормально. Ну что ж, тупить я умею

Всем пасибо

#13
8:21, 2 окт. 2006

Возникли новые вопросы :(((
Опять-таки они касаются пропуска некоторых блоков (чанков).
Ситуация такая:
два совершенно идентичных файла .3ds формата, только один с кубом, а другой с пирамидой
вот чанки, которые находятся в файле с кубом (справа - позиция курсора в файле)

CHUNK_MAIN___________0
CHUNK_VERSIONF_______6
CHUNK_OBJBLOK_______42
CHUNK_TRIMESH_______54
CHUNK_VERTLIST_______60
CHUNK_FACELIST_______290
Как видно, здесь все правильно.
а вот для пирамиды:
CHUNK_MAIN___________0
CHUNK_VERSIONF_______6
CHUNK_OBJBLOK_______42
CHUNK_VERSIONF______372
Самое интересное, что если попытаться из куба сделать пирамиду, т.е. 4 вершины объединить в одну, то все опять сработает! Но если, скажем, на противоположных сторонах куба объединить по две вершины или добавит где-нибудь вершину, то опять все наперекосяк. 
В общем, все блоки находятся правильно только для куба, т.е. для параллелепипеда.
Может кто-нибудь сталкивался с подобной проблемой?

вот кусок кода:

  unsigned short id_chunk = 0;  //id текущего блока
  unsigned int len_chunk = 0;  //его длина

  while (pos < maxpos)
  {
    pos = ftell(fl);
    fread(&id_chunk, 2, 1, fl);
    fread(&len_chunk, 4, 1, fl);
    
      len_chunk -= 6;  //уменьшаем на 6 уже считанных байт
      
      switch (id_chunk)  //ищем нужный блок
      {
      case CHUNK_MAIN: 
        cout << "CHUNK_MAIN______" << pos << " \n";
        break;
      case CHUNK_VERSIONF:
        cout << "CHUNK_VERSIONF______" << pos << " \n";
        break;
      case CHUNK_OBJMESH:
        cout << "CHUCK_OBJMESH______" << pos << " \n";
        break;
      case CHUNK_OBJBLOCK:
        cout << "CHUNK_OBJBLOCK______" << pos << " \n";
        break;
      case CHUNK_TRIMESH:
        cout << "CHUCK_TRIMESH______" << pos << " \n";
        break;
      case CHUNK_VERTLIST:
        cout << "CHUCK_VERTLIST______" << pos << " \n";
        fseek(fl, pos + len_chunk, SEEK_SET);
        break;
      case CHUNK_FACELIST:
        cout << "CHUNK_FACELIST______" << pos << " \n";
        fseek(fl, pos + len_chunk, SEEK_SET);
        break;
      
      default: break;
      }
    
Как видно, здесь просто происходит поиск чанков
Так почему же для куба все ищется идеально, а для (почти) любой другой фигуры - нет?

#14
20:06, 2 окт. 2006

вопрос отпал. уже все сработало (на данной стадии)

всем опять пасибо

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

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