Блоґ одного кібера

Історія хвороби контуженого інформаційним вибухом

Розшифрування формату 3ds

with one comment

Тобто перетворення з бінарного формату в текстовий, з виділенням основної інформації. Завантаження тривимірної моделі з текстового файлу не являє собою великої проблеми.

Файли 3ds складаються з кусків (chuncks). Кожен кусок містить іформацію про конкретний об’єкт. Кусок може мати підкуски. Всі вони містяться всередині одного головного.

Тривимірні моделі являють собою сітку трикутників (triangle mesh). Кожен трикутник – це номери трьох вершин (vertices), нумерація починається з нуля. А вершина – це три координати, і дві текстурні координати.

Мій конвертер базується на статті Damiano Vitulli. В ній ви можете прочитати про формат 3ds детальніше. Також є стаття на gamedev.ru.

Формат

Результатом роботи програми є текстовий файл, який містить список об’єктів файлу.

Кожен об’єкт починається рядком "N 1", що значить, що далі буде одна назва об’єкта. Назва об’єкта – просто рядок символів, яким об’єкт ідентифікували в 3d редакторі.

Далі ідуть блоки, які задають геометрію об’єкта. Початок кожного з них позначається рядком з буквою і числом. Число показує кількість рядків блоку.

  • Буква V(Vertices) позначає список вершин. В цьому блоці кожен рядок містить три дійсні числа – координати вершини.
  • Буква M(Mapping) позначає список текстурних координат. В цьому блоці кожен рядок містить два дійсні числа – текстурні координати вершини. Кількість текстурних кординат мала б бути такою ж як і кількість вершин.
  • Буква P(Polygons) позначає список граней. В цьому блоці кожен рядок містить три цілі числа – номери вершин трикутника. Грані в 3ds бувають тільки трикутні.

Оце і все. Добре було б ще мати нормалі до кожної вершини, але на жаль, їх прийдеться обчислювати вручну. Або взагалі не обчислювати. Як воно працює з анімаціями, я не знаю. Скоріш за все також не працює. Але це все таки краще, ніж набридлий усім кубик, що обертається.

Що з цим робити далі, читайте в наступній статті. Там також є гарні картинки :).

Код

/*
    Program for converting 3ds into text files
    Copyleft: Bunyk T. www.bunyk.wordpress.com
*/


#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>

long filelength(int f)
{
    struct stat buf;

    fstat(f, &buf);

    return(buf.st_size);
}

void Convert3DS (char *p_filename,char *resfilename)
{
	int i; //Index variable
	FILE *l_file; //File pointer

    FILE *rfile; // resultfile

    float tmp; // temporary variables, for loading from files
    unsigned short tmpi;

	unsigned short l_chunk_id; //Chunk identifier
	unsigned int l_chunk_lenght; //Chunk lenght

	unsigned char l_char; //Char variable
	unsigned short l_qty; //Number of elements in each chunk

	unsigned short l_face_flags; //Flag that stores some face information

	if ((l_file=fopen (p_filename, "rb"))== NULL) return 0; //Open the file
	if ((rfile=fopen (resfilename, "wt"))== NULL) return 0; //Open the result file

	while (ftell (l_file) < filelength (fileno (l_file))) //Loop to scan the whole file
	//while(!EOF)
	{
		//getchar(); //Insert this command for debug (to wait for keypress for each chuck reading)

		fread (&l_chunk_id, 2, 1, l_file); //Read the chunk header
		fread (&l_chunk_lenght, 4, 1, l_file); //Read the lenght of the chunk

		switch (l_chunk_id)
        {
			//----------------- MAIN3DS -----------------
			// Description: Main chunk, contains all the other chunks
			// Chunk ID: 4d4d
			// Chunk Lenght: 0 + sub chunks
			//-------------------------------------------
			case 0x4d4d:
			break;

			//----------------- EDIT3DS -----------------
			// Description: 3D Editor chunk, objects layout info
			// Chunk ID: 3d3d (hex)
			// Chunk Lenght: 0 + sub chunks
			//-------------------------------------------
			case 0x3d3d:
			break;

			//--------------- EDIT_OBJECT ---------------
			// Description: Object block, info for each object
			// Chunk ID: 4000 (hex)
			// Chunk Lenght: len(object name) + sub chunks
			//-------------------------------------------
			case 0x4000:
                fprintf(rfile,"N 1\n");
				i=0;
				do
				{
					fread (&l_char, 1, 1, l_file);
                    if(l_char) fprintf(rfile,"%c",l_char);
					i++;
                }while(l_char != '' && i<20);
                fprintf(rfile,"\n");
			break;

			//--------------- OBJ_TRIMESH ---------------
			// Description: Triangular mesh, contains chunks for 3d mesh info
			// Chunk ID: 4100 (hex)
			// Chunk Lenght: 0 + sub chunks
			//-------------------------------------------
			case 0x4100:
			break;

			//--------------- TRI_VERTEXL ---------------
			// Description: Vertices list
			// Chunk ID: 4110 (hex)
			// Chunk Lenght: 1 x unsigned short (number of vertices)
			//             + 3 x float (vertex coordinates) x (number of vertices)
			//             + sub chunks
			//-------------------------------------------
			case 0x4110:
				fread (&l_qty, sizeof (unsigned short), 1, l_file);
                fprintf(rfile,"V %d\n",l_qty);
                for (i=0; i<l_qty; i++)
                {
					fread (&tmp, sizeof(float), 1, l_file);
 					fprintf(rfile,"%f",tmp);
                    fread (&tmp, sizeof(float), 1, l_file);
 					fprintf(rfile," %f",tmp);
					fread (&tmp, sizeof(float), 1, l_file);
 					fprintf(rfile," %f\n",tmp);
				}
				break;

			//--------------- TRI_FACEL1 ----------------
			// Description: Polygons (faces) list
			// Chunk ID: 4120 (hex)
			// Chunk Lenght: 1 x unsigned short (number of polygons)
			//             + 3 x unsigned short (polygon points) x (number of polygons)
			//             + sub chunks
			//-------------------------------------------
			case 0x4120:
				fread (&l_qty, sizeof (unsigned short), 1, l_file);
                //p_object->polygons_qty = l_qty;
                fprintf(rfile,"P %d\n",l_qty);
                for (i=0; i<l_qty; i++)
                {
					fread (&tmpi, sizeof (unsigned short), 1, l_file);
					fprintf(rfile,"%d",tmpi);
					fread (&tmpi, sizeof (unsigned short), 1, l_file);
					fprintf(rfile," %d",tmpi);
					fread (&tmpi, sizeof (unsigned short), 1, l_file);
					fprintf(rfile," %d\n",tmpi);
					fread (&l_face_flags, sizeof (unsigned short), 1, l_file);
				}
                break;

			//------------- TRI_MAPPINGCOORS ------------
			// Description: Vertices list
			// Chunk ID: 4140 (hex)
			// Chunk Lenght: 1 x unsigned short (number of mapping points)
			//             + 2 x float (mapping coordinates) x (number of mapping points)
			//             + sub chunks
			//-------------------------------------------
			case 0x4140:
				fread (&l_qty, sizeof (unsigned short), 1, l_file);
				fprintf(rfile,"M %d\n",l_qty);
				for (i=0; i<l_qty; i++)
				{
					fread (&tmp, sizeof (float), 1, l_file);
					fprintf(rfile,"%f",tmp);
                    fread (&tmp, sizeof (float), 1, l_file);
					fprintf(rfile," %f\n",tmp);
				}
                break;

			//----------- Skip unknow chunks ------------
			//We need to skip all the chunks that currently we don't use
			//We use the chunk lenght information to set the file pointer
			//to the same level next chunk
			//-------------------------------------------
			default:
				 fseek(l_file, l_chunk_lenght-6, SEEK_CUR);
        }
	}
	fclose (l_file); // Closes the file stream
	fclose (rfile);
}

int main()
{
    char fn[50];
    char nfn[50];
	printf("Input 3ds file name: "); scanf("%s",fn);
    printf("Input result file name:"); scanf("%s",nfn);

	Convert3DS(fn,nfn);

	return 0;
}
Advertisements

Written by bunyk

Травень 22, 2009 at 18:50

Оприлюднено в Графіка, Кодерство

Tagged with ,

Одна відповідь

Subscribe to comments with RSS.

  1. Чорт, як жаль, що я не читав твій блог тоді, я також колись таким страждав:
    http://www.delphisources.ru/pages/sources/graph/2008-year/3ds-viewer.html

    dmytrish

    Вересень 24, 2012 at 23:22


Залишити відповідь

Заповніть поля нижче або авторизуйтесь клікнувши по іконці

Лого WordPress.com

Ви коментуєте, використовуючи свій обліковий запис WordPress.com. Log Out / Змінити )

Twitter picture

Ви коментуєте, використовуючи свій обліковий запис Twitter. Log Out / Змінити )

Facebook photo

Ви коментуєте, використовуючи свій обліковий запис Facebook. Log Out / Змінити )

Google+ photo

Ви коментуєте, використовуючи свій обліковий запис Google+. Log Out / Змінити )

З’єднання з %s

%d блогерам подобається це: