예제 #1
0
파일: 3ds.cpp 프로젝트: jchristi/ta3d
    MODEL *load_3ds( const String &filename, float scale )
    {
        FILE *src_3ds = fopen( filename.c_str(), "rb" );
        MODEL *model_3ds = new MODEL;
        if (src_3ds)
        {
            TA3D_3DS_CHUNK_DATA	chunk;
            OBJECT *cur_obj = NULL;
            OBJECT *read_obj = NULL;
            TA3D_3DS_MATERIAL	*material = NULL;
            Vector3D local[4];
            while( fread( &chunk.ID, sizeof( chunk.ID ), 1, src_3ds ) )
            {
                if( fread( &chunk.length, sizeof( chunk.length ), 1, src_3ds ) == 0 )	break;
                switch( chunk.ID )
                {
                    case MAIN3DS:
                        //				printf("MAIN3DS (%d,%d)\n", chunk.ID, chunk.length);
                        break;
                    case EDIT3DS:
                        //					printf("-EDIT3DS (%d,%d)\n", chunk.ID, chunk.length);
                        break;
                    case EDIT_MATERIAL:
                        //						printf("--EDIT_MATERIAL (%d,%d)\n", chunk.ID, chunk.length);
                        {
                            TA3D_3DS_MATERIAL	*new_mat = new TA3D_3DS_MATERIAL;
                            new_mat->next = material;
                            material = new_mat;
                        }
                        break;
                    case MAT_NAME:
                        //							printf("---MAT_NAME (%d,%d)\n", chunk.ID, chunk.length);
                        {
                            String name = read_ASCIIZ( src_3ds );
                            //								printf( "name = %s\n", name );
                            if( material )
                                material->NAME = name;
                        }
                        break;
                    case MAT_AMBIENT:
                        //							printf("---MAT_AMBIENT (%d,%d)\n", chunk.ID, chunk.length);
                        if( material )
                            read_color_chunk( material->AMBIENT, src_3ds );
                        else
                            fseek( src_3ds, chunk.length - 6, SEEK_CUR );
                        break;
                    case MAT_DIFFUSE:
                        //							printf("---MAT_DIFFUSE (%d,%d)\n", chunk.ID, chunk.length);
                        if( material )
                            read_color_chunk( material->DIFFUSE, src_3ds );
                        else
                            fseek( src_3ds, chunk.length - 6, SEEK_CUR );
                        break;
                    case MAT_SPECULAR:
                        //							printf("---MAT_SPECULAR (%d,%d)\n", chunk.ID, chunk.length);
                        if( material )
                            read_color_chunk( material->SPECULAR, src_3ds );
                        else
                            fseek( src_3ds, chunk.length - 6, SEEK_CUR );
                        break;
                    case MAT_SHININESS:
                        //							printf("---MAT_SHININESS (%d,%d)\n", chunk.ID, chunk.length);
                        if( material )
                            material->SHININESS = read_percent_chunk( src_3ds );
                        else
                            fseek( src_3ds, chunk.length - 6, SEEK_CUR );
                        break;
                    case MAT_SHIN2PCT:
                        //							printf("---MAT_SHIN2PCT (%d,%d)\n", chunk.ID, chunk.length);
                        if( material )
                            material->SHIN2PCT = read_percent_chunk( src_3ds );
                        else
                            fseek( src_3ds, chunk.length - 6, SEEK_CUR );
                        break;
                    case MAT_SHIN3PCT:
                        //							printf("---MAT_SHIN3PCT (%d,%d)\n", chunk.ID, chunk.length);
                        if( material )
                            material->SHIN3PCT = read_percent_chunk( src_3ds );
                        else
                            fseek( src_3ds, chunk.length - 6, SEEK_CUR );
                        break;
                    case MAT_TRANSPARENCY:
                        //							printf("---MAT_TRANSPARENCY (%d,%d)\n", chunk.ID, chunk.length);
                        if( material )
                            material->TRANSPARENCY = read_percent_chunk( src_3ds );
                        else
                            fseek( src_3ds, chunk.length - 6, SEEK_CUR );
                        break;
                    case MAT_TWO_SIDE:
                        //							printf("---MAT_TWO_SIDE (%d,%d)\n", chunk.ID, chunk.length);
                        if( material )
                            material->TWO_SIDE = true;
                        fseek( src_3ds, chunk.length - 6, SEEK_CUR );
                        break;
                    case MAT_TEXMAP:
                        //							printf("---MAT_TEXMAP (%d,%d)\n", chunk.ID, chunk.length);
                        if( material ) {
                            uint16 n_id;
                            fread( &n_id, 2, 1, src_3ds );
                            fseek( src_3ds, -2, SEEK_CUR );
                            if( n_id == MAT_MAPNAME ) {
                                material->MAPNAME = read_MAT_MAPNAME_chunk( src_3ds );
                                material->TEXMAP = read_percent_chunk( src_3ds );
                            }
                            else {
                                material->TEXMAP = read_percent_chunk( src_3ds );
                                material->MAPNAME = read_MAT_MAPNAME_chunk( src_3ds );
                            }
                            char *full_name = new char[2048];
                            replace_filename( full_name, filename.c_str(), material->MAPNAME.c_str(), 2048 );
                            material->MAPNAME = full_name;
                            delete[] full_name;
                        }
                        else
                            fseek( src_3ds, chunk.length - 6, SEEK_CUR );
                        break;
                    case EDIT_CONFIG1:
                        //						printf("--EDIT_CONFIG1 (%d,%d)\n", chunk.ID, chunk.length);
                        fseek( src_3ds, chunk.length - 6, SEEK_CUR );
                        break;
                    case EDIT_CONFIG2:
                        //						printf("--EDIT_CONFIG2 (%d,%d)\n", chunk.ID, chunk.length);
                        fseek( src_3ds, chunk.length - 6, SEEK_CUR );
                        break;
                    case EDIT_VIEW_P1:
                        //						printf("--EDIT_VIEW_P1 (%d,%d)\n", chunk.ID, chunk.length);
                        fseek( src_3ds, chunk.length - 6, SEEK_CUR );
                        break;
                    case EDIT_VIEW_P2:
                        //						printf("--EDIT_VIEW_P2 (%d,%d)\n", chunk.ID, chunk.length);
                        fseek( src_3ds, chunk.length - 6, SEEK_CUR );
                        break;
                    case EDIT_VIEW_P3:
                        //						printf("--EDIT_VIEW_P2 (%d,%d)\n", chunk.ID, chunk.length);
                        fseek( src_3ds, chunk.length - 6, SEEK_CUR );
                        break;
                    case EDIT_VIEW1:
                        //						printf("--EDIT_VIEW1 (%d,%d)\n", chunk.ID, chunk.length);
                        fseek( src_3ds, chunk.length - 6, SEEK_CUR );
                        break;
                    case EDIT_BACKGR:
                        //						printf("--EDIT_BACKGR (%d,%d)\n", chunk.ID, chunk.length);
                        fseek( src_3ds, chunk.length - 6, SEEK_CUR );
                        break;
                    case EDIT_AMBIENT:
                        //						printf("--EDIT_AMBIENT (%d,%d)\n", chunk.ID, chunk.length);
                        fseek( src_3ds, chunk.length - 6, SEEK_CUR );
                        break;
                    case EDIT_OBJECT:
                        //						printf("--EDIT_OBJECT (%d,%d)\n", chunk.ID, chunk.length);
                        {
                            OBJECT	*n_obj = new OBJECT;
                            n_obj->next = cur_obj;
                            cur_obj = n_obj;
                        }
                        cur_obj->name = read_ASCIIZ( src_3ds );		// Read the object's name
                        read_obj = cur_obj;
                        break;
                    case OBJ_LIGHT:
                        //							printf("---OBJ_LIGHT (%d,%d)\n", chunk.ID, chunk.length);
                        fseek( src_3ds, chunk.length - 6, SEEK_CUR );
                        break;
                    case OBJ_CAMERA:
                        //							printf("---OBJ_CAMERA (%d,%d)\n", chunk.ID, chunk.length);
                        fseek( src_3ds, chunk.length - 6, SEEK_CUR );
                        break;
                    case OBJ_UNKNWN01:
                        //							printf("---OBJ_UNKNWN01 (%d,%d)\n", chunk.ID, chunk.length);
                        fseek( src_3ds, chunk.length - 6, SEEK_CUR );
                        break;
                    case OBJ_UNKNWN02:
                        //							printf("---OBJ_UNKNWN02 (%d,%d)\n", chunk.ID, chunk.length);
                        fseek( src_3ds, chunk.length - 6, SEEK_CUR );
                        break;
                    case OBJ_TRIMESH:
                        //							printf("---OBJ_TRIMESH (%d,%d)\n", chunk.ID, chunk.length);
                        if( read_obj->nb_vtx > 0 ) {		// Add a sub object
                            read_obj->child = new OBJECT;
                            read_obj = read_obj->child;
                            read_obj->init();
                            read_obj->name = cur_obj->name;
                        }
                        local[0].x = 1.0f;		local[0].y = 0.0f;		local[0].z = 0.0f;
                        local[1].x = 0.0f;		local[1].y = 1.0f;		local[1].z = 0.0f;
                        local[2].x = 0.0f;		local[2].y = 0.0f;		local[2].z = 1.0f;
                        local[3].x = 0.0f;		local[3].y = 0.0f;		local[3].z = 0.0f;
                        break;
                    case TRI_VERTEXL:
                        //								printf("----TRI_VERTEXL (%d,%d)\n", chunk.ID, chunk.length);
                        fread( &read_obj->nb_vtx, 2, 1, src_3ds );
                        read_obj->points = new Vector3D[read_obj->nb_vtx];
                        read_obj->N = new Vector3D[read_obj->nb_vtx];
                        if( read_obj->tcoord == NULL )
                        {
                            read_obj->tcoord = new float[read_obj->nb_vtx * 2];
                            for( int i = 0 ; i < read_obj->nb_vtx ; i++ )
                            {
                                read_obj->tcoord[ i << 1 ] = 0.0f;
                                read_obj->tcoord[ (i << 1) + 1 ] = 0.0f;
                            }
                        }
                        fread( read_obj->points, sizeof( Vector3D ), read_obj->nb_vtx, src_3ds );
                        for( int i = 0 ; i < read_obj->nb_vtx ; i++ ) {
                            read_obj->points[ i ] = read_obj->points[ i ].x * local[ 0 ] + read_obj->points[ i ].y * local[ 1 ] + read_obj->points[ i ].z * local[ 2 ] + local[ 3 ];
                            read_obj->points[ i ].x *= scale;
                            read_obj->points[ i ].y *= scale;
                            read_obj->points[ i ].z *= scale;
                            read_obj->N[ i ].x = read_obj->N[ i ].y = read_obj->N[ i ].z = 0.0f;
                        }
                        break;
                    case TRI_FACEL2:
                        //								printf("----TRI_FACEL2 (%d,%d)\n", chunk.ID, chunk.length);
                        fseek( src_3ds, chunk.length - 6, SEEK_CUR );
                        break;
                    case TRI_MATERIAL:
                        //								printf("----TRI_MATERIAL (%d,%d)\n", chunk.ID, chunk.length);
                        {
                            String material_name = read_ASCIIZ( src_3ds );
                            //									printf("material name = %s\n", material_name );

                            TA3D_3DS_MATERIAL	*cur_mat = (material != NULL) ? material->find( material_name ) : NULL ;

                            if (cur_mat)
                            {
                                //										printf("material found\n");
                                read_obj->surface.Flag |= SURFACE_ADVANCED | SURFACE_LIGHTED;
                                if (!cur_mat->MAPNAME.empty())
                                {
                                    //											printf("loading texture %s\n", cur_mat->MAPNAME );
                                    read_obj->surface.Flag |= SURFACE_TEXTURED;
                                    read_obj->surface.NbTex = 1;
                                    cHPIHandler *backup = HPIManager;
                                    HPIManager = NULL;
                                    read_obj->surface.gltex[ 0 ] = gfx->load_texture( cur_mat->MAPNAME );
                                    HPIManager = backup;
                                }
                                if (cur_mat->TRANSPARENCY > 0.0f)
                                {
                                    read_obj->surface.Flag |= SURFACE_BLENDED;
                                    read_obj->surface.Color[ 3 ] = cur_mat->TRANSPARENCY;
                                }
                            }
                            else
                                printf("WARNING: material not found!!\n");

                            uint16	nb_faces;
                            fread( &nb_faces, 2, 1, src_3ds );
                            for( int i = 0 ; i < nb_faces ; i++ ) {
                                uint16 cur_face;
                                fread( &cur_face, 2, 1, src_3ds );
                            }
                        }
                        break;
                    case TRI_MAPPING:
                        //								printf("----TRI_MAPPING (%d,%d)\n", chunk.ID, chunk.length);
                        {
                            uint16	nb_vtx;
                            fread( &nb_vtx, 2, 1, src_3ds );
                            if( read_obj->tcoord == NULL )
                                read_obj->tcoord = new float[2 * nb_vtx];
                            fread( read_obj->tcoord, 2 * sizeof( float ), nb_vtx, src_3ds );
                            for( int i = 0 ; i < nb_vtx ; i++ )
                                read_obj->tcoord[ i * 2 + 1 ] = 1.0f - read_obj->tcoord[ i * 2 + 1 ];
                        }
                        break;
                    case TRI_FACEL1:
                        //								printf("----TRI_FACEL1 (%d,%d)\n", chunk.ID, chunk.length);
                        fread( &read_obj->nb_t_index, 2, 1, src_3ds );
                        read_obj->t_index = new GLushort[read_obj->nb_t_index * 3];
                        read_obj->nb_t_index *= 3;
                        for( int i = 0 ; i < read_obj->nb_t_index ; i+=3 ) {
                            fread( &(read_obj->t_index[ i ]), 2, 3, src_3ds );
                            if( read_obj->points ) {
                                Vector3D AB,AC;
                                AB = read_obj->points[ read_obj->t_index[ i + 1 ] ] - read_obj->points[ read_obj->t_index[ i ] ];
                                AC = read_obj->points[ read_obj->t_index[ i + 2 ] ] - read_obj->points[ read_obj->t_index[ i ] ];
                                AB = AB * AC;
                                AB.unit();
                                read_obj->N[ read_obj->t_index[ i ] ] = read_obj->N[ read_obj->t_index[ i ] ] + AB;
                                read_obj->N[ read_obj->t_index[ i + 1 ] ] = read_obj->N[ read_obj->t_index[ i + 1 ] ] + AB;
                                read_obj->N[ read_obj->t_index[ i + 2 ] ] = read_obj->N[ read_obj->t_index[ i + 2 ] ] + AB;
                            }
                            uint16 face_info;
                            fread( &face_info, 2, 1, src_3ds );
                        }
                        if( read_obj->points )
                            for( int i = 0 ; i < read_obj->nb_vtx ; i++ )
                                read_obj->N[ i ].unit();
                        break;
                    case TRI_SMOOTH:
                        //								printf("----TRI_SMOOTH (%d,%d)\n", chunk.ID, chunk.length);
                        fseek( src_3ds, chunk.length - 6, SEEK_CUR );
                        break;
                    case TRI_LOCAL:
                        //								printf("----TRI_LOCAL (%d,%d)\n", chunk.ID, chunk.length);
                        fread( &(local[0]), sizeof( Vector3D ), 1, src_3ds );		// X
                        fread( &(local[1]), sizeof( Vector3D ), 1, src_3ds );		// Y
                        fread( &(local[2]), sizeof( Vector3D ), 1, src_3ds );		// Z
                        fread( &(local[3]), sizeof( Vector3D ), 1, src_3ds );		// local origin
                        break;
                    case TRI_VISIBLE:
                        //								printf("----TRI_VISIBLE (%d,%d)\n", chunk.ID, chunk.length);
                        fseek( src_3ds, chunk.length - 6, SEEK_CUR );
                        break;
                    default:
                        //				printf("unknown (%d,%d)\n", chunk.ID, chunk.length);
                        fseek( src_3ds, chunk.length - 6, SEEK_CUR );
                }
            }
            if( material )
                delete material;
            if (cur_obj)
            {
                model_3ds->obj = *cur_obj;
                cur_obj->init();
                delete cur_obj;
            }
            fclose( src_3ds );
        }
        return model_3ds;
    }
예제 #2
0
	Model *Mesh3DS::load(const String &filename)
	{
		File *file = VFS::Instance()->readFile(filename);

		if (!file || !file->isOpen())
			return NULL;

		Mesh3DS *firstObj = new Mesh3DS;
		Mesh3DS *cur_obj = NULL;
		Mesh3DS *read_obj = NULL;
		HashMap<Material*>::Dense material;
		Material *currentMat = NULL;
		Vector3D local[4];
		while (!file->eof())
		{
			ChunkData chunk;
			*file >> chunk.ID;
			*file >> chunk.length;
			if (file->eof())
				break;
			switch (chunk.ID)
			{
			case MAIN3DS:
				PRINT_DEBUG("MAIN3DS (" << chunk.ID << ',' << chunk.length << ')');
				break;
			case EDIT3DS:
				PRINT_DEBUG("-EDIT3DS (" << chunk.ID << ',' << chunk.length << ')');
				break;
			case EDIT_MATERIAL:
				PRINT_DEBUG("-EDIT_MATERIAL (" << chunk.ID << ',' << chunk.length << ')');
				if (currentMat && currentMat->name.empty())
					delete currentMat;
				currentMat = new Material;
				break;
			case MAT_NAME:
				PRINT_DEBUG("-MAT_NAME (" << chunk.ID << ',' << chunk.length << ')');
				{
					String name = file->getString();
					PRINT_DEBUG("name = " << name);
					if (currentMat)
					{
						currentMat->name = name;
						if (!name.empty())
						{
							if (material.count(name)
								&& material[name] != currentMat
								&& material[name] != NULL)
								delete material[name];
							material[name] = currentMat;
						}
					}
				}
				break;
			case MAT_AMBIENT:
				PRINT_DEBUG("-MAT_AMBIENT (" << chunk.ID << ',' << chunk.length << ')');
				if (currentMat)
					read_color_chunk( currentMat->ambient, file );
				else
					file->seek( file->tell() + chunk.length - 6 );
				break;
			case MAT_DIFFUSE:
				PRINT_DEBUG("-MAT_DIFFUSE (" << chunk.ID << ',' << chunk.length << ')');
				if (currentMat)
					read_color_chunk( currentMat->diffuse, file );
				else
					file->seek( file->tell() + chunk.length - 6 );
				break;
			case MAT_SPECULAR:
				PRINT_DEBUG("-MAT_SPECULAR (" << chunk.ID << ',' << chunk.length << ')');
				if (currentMat)
					read_color_chunk( currentMat->specular, file );
				else
					file->seek( file->tell() + chunk.length - 6 );
				break;
			case MAT_SHININESS:
				PRINT_DEBUG("-MAT_SHININESS (" << chunk.ID << ',' << chunk.length << ')');
				if (currentMat)
					currentMat->shininess = read_percent_chunk( file );
				else
					file->seek( file->tell() + chunk.length - 6 );
				break;
			case MAT_SHIN2PCT:
				PRINT_DEBUG("-MAT_SHIN2PCT (" << chunk.ID << ',' << chunk.length << ')');
				if (currentMat)
					currentMat->shin2pct = read_percent_chunk( file );
				else
					file->seek( file->tell() + chunk.length - 6 );
				break;
			case MAT_SHIN3PCT:
				PRINT_DEBUG("-MAT_SHIN3PCT (" << chunk.ID << ',' << chunk.length << ')');
				if (currentMat)
					currentMat->shin3pct = read_percent_chunk( file );
				else
					file->seek( file->tell() + chunk.length - 6 );
				break;
			case MAT_TRANSPARENCY:
				PRINT_DEBUG("-MAT_TRANSPARENCY (" << chunk.ID << ',' << chunk.length << ')');
				if (currentMat)
					currentMat->transparency = read_percent_chunk( file );
				else
					file->seek( file->tell() + chunk.length - 6 );
				break;
			case MAT_TWO_SIDE:
				PRINT_DEBUG("-MAT_TWO_SIDE (" << chunk.ID << ',' << chunk.length << ')');
				if (currentMat)
					currentMat->twoSide = true;
				file->seek( file->tell() + chunk.length - 6 );
				break;
			case MAT_TEXMAP:
				PRINT_DEBUG("-MAT_TEXMAP (" << chunk.ID << ',' << chunk.length << ')');
				if (currentMat)
				{
					uint16 n_id;
					*file >> n_id;
					file->seek(file->tell() - 2);
					if (n_id == MAT_MAPNAME)
					{
						currentMat->mapname = read_MatMapname_chunk( file );
						currentMat->texmap = read_percent_chunk( file );
					}
					else
					{
						currentMat->texmap = read_percent_chunk( file );
						currentMat->mapname = read_MatMapname_chunk( file );
					}
					currentMat->mapname = String("textures/") << currentMat->mapname;
					PRINT_DEBUG("texmap : " << currentMat->mapname);
				}
				else
					file->seek( file->tell() + chunk.length - 6 );
				break;
            case EDIT_CONFIG1:
				PRINT_DEBUG("-EDIT_CONFIG1 (" << chunk.ID << ',' << chunk.length << ')');
				file->seek( file->tell() + chunk.length - 6 );
				break;
            case EDIT_CONFIG2:
				PRINT_DEBUG("-EDIT_CONFIG2 (" << chunk.ID << ',' << chunk.length << ')');
				file->seek( file->tell() + chunk.length - 6 );
				break;
            case EDIT_VIEW_P1:
				PRINT_DEBUG("-EDIT_VIEW_P1 (" << chunk.ID << ',' << chunk.length << ')');
				file->seek( file->tell() + chunk.length - 6 );
				break;
            case EDIT_VIEW_P2:
				PRINT_DEBUG("-EDIT_VIEW_P2 (" << chunk.ID << ',' << chunk.length << ')');
				file->seek( file->tell() + chunk.length - 6 );
				break;
            case EDIT_VIEW_P3:
				PRINT_DEBUG("-EDIT_VIEW_P3 (" << chunk.ID << ',' << chunk.length << ')');
				file->seek( file->tell() + chunk.length - 6 );
				break;
            case EDIT_VIEW1:
				PRINT_DEBUG("-EDIT_VIEW1 (" << chunk.ID << ',' << chunk.length << ')');
				file->seek( file->tell() + chunk.length - 6 );
				break;
            case EDIT_BACKGR:
				PRINT_DEBUG("-EDIT_BACKGR (" << chunk.ID << ',' << chunk.length << ')');
				file->seek( file->tell() + chunk.length - 6 );
				break;
			case EDIT_AMBIENT:
				PRINT_DEBUG("-EDIT_AMBIENT (" << chunk.ID << ',' << chunk.length << ')');
				file->seek( file->tell() + chunk.length - 6 );
				break;
            case EDIT_OBJECT:
				PRINT_DEBUG("-EDIT_OBJECT (" << chunk.ID << ',' << chunk.length << ')');
				if (cur_obj)
				{
					Mesh3DS *n_obj = new Mesh3DS;
					cur_obj->next = n_obj;
					cur_obj = n_obj;
				}
				else
					cur_obj = firstObj;
				cur_obj->type = MESH_TYPE_TRIANGLES;
				cur_obj->name = file->getString();		// Read the object's name
				cur_obj->Flag = SURFACE_ADVANCED | SURFACE_GOURAUD | SURFACE_LIGHTED;
				read_obj = cur_obj;
				break;
            case OBJ_LIGHT:
				PRINT_DEBUG("-OBJ_LIGHT (" << chunk.ID << ',' << chunk.length << ')');
				file->seek( file->tell() + chunk.length - 6 );
				break;
            case OBJ_CAMERA:
				PRINT_DEBUG("-OBJ_CAMERA (" << chunk.ID << ',' << chunk.length << ')');
				file->seek( file->tell() + chunk.length - 6 );
				break;
            case OBJ_UNKNWN01:
				PRINT_DEBUG("-OBJ_UNKNWN01 (" << chunk.ID << ',' << chunk.length << ')');
				file->seek( file->tell() + chunk.length - 6 );
				break;
            case OBJ_UNKNWN02:
				PRINT_DEBUG("-OBJ_UNKNWN02 (" << chunk.ID << ',' << chunk.length << ')');
				file->seek( file->tell() + chunk.length - 6 );
				break;
            case OBJ_TRIMESH:
				PRINT_DEBUG("-OBJ_TRIMESH (" << chunk.ID << ',' << chunk.length << ')');
				if (read_obj->nb_vtx > 0)		// Add a sub object
				{
					read_obj->child = new Mesh3DS;
					read_obj = static_cast<Mesh3DS*>(read_obj->child);
					read_obj->type = MESH_TYPE_TRIANGLES;
					read_obj->name = cur_obj->name;
					read_obj->Flag = SURFACE_ADVANCED | SURFACE_GOURAUD | SURFACE_LIGHTED;
				}
				local[0].x = 1.0f;		local[0].y = 0.0f;		local[0].z = 0.0f;
				local[1].x = 0.0f;		local[1].y = 1.0f;		local[1].z = 0.0f;
				local[2].x = 0.0f;		local[2].y = 0.0f;		local[2].z = 1.0f;
				local[3].x = 0.0f;		local[3].y = 0.0f;		local[3].z = 0.0f;
				break;
            case TRI_VERTEXL:
				{
					PRINT_DEBUG("-TRI_VERTEXL (" << chunk.ID << ',' << chunk.length << ')');
					uint16 nb_vtx;
					*file >> nb_vtx;
					read_obj->nb_vtx = nb_vtx;
					read_obj->points = new Vector3D[nb_vtx << 1];
					read_obj->N = new Vector3D[nb_vtx << 1];
					if (read_obj->tcoord == NULL)
					{
						read_obj->tcoord = new float[nb_vtx * 2];
						for (int i = 0 ; i < read_obj->nb_vtx ; ++i)
						{
							read_obj->tcoord[ i << 1 ] = 0.0f;
							read_obj->tcoord[ (i << 1) + 1 ] = 0.0f;
						}
					}
					file->read( (char*)read_obj->points, (int)sizeof( Vector3D ) * nb_vtx );
					for (int i = 0 ; i < read_obj->nb_vtx ; ++i)
					{
						read_obj->points[ i ] = read_obj->points[ i ].x * local[ 0 ] + read_obj->points[ i ].y * local[ 1 ] + read_obj->points[ i ].z * local[ 2 ] + local[ 3 ];
						read_obj->N[ i ].reset();
					}
				}
				break;
            case TRI_FACEL2:
				PRINT_DEBUG("-TRI_FACEL2 (" << chunk.ID << ',' << chunk.length << ')');
				file->seek( file->tell() + chunk.length - 6 );
				break;
			case TRI_MATERIAL:
				PRINT_DEBUG("-TRI_MATERIAL (" << chunk.ID << ',' << chunk.length << ')');
				{
					String material_name = file->getString();
					PRINT_DEBUG("material name = " << material_name);

					Material *cur_mat = material[material_name];

					if (cur_mat)
					{
						PRINT_DEBUG("material found");
						if (!cur_mat->mapname.empty())
						{
							PRINT_DEBUG("loading texture " << cur_mat->mapname);
							read_obj->Flag |= SURFACE_TEXTURED;
							String name = cur_mat->mapname;
							name.trim();
							read_obj->tex_cache_name.push_back(name);
						}
						if (cur_mat->transparency > 0.0f)
						{
							read_obj->Flag |= SURFACE_BLENDED;
							read_obj->Color = (read_obj->Color & 0xFFFFFF00) | (uint32)(cur_mat->transparency * 255);
						}
						if (cur_mat->name == "team")			// The magic team material
						{
							read_obj->Flag |= SURFACE_PLAYER_COLOR;
						}
					}
					else
						LOG_WARNING(LOG_PREFIX_3DS << "WARNING: material not found!!");

					uint16	nb_faces;
					*file >> nb_faces;
					for( int i = 0 ; i < nb_faces ; i++ )
					{
						uint16 cur_face;
						*file >> cur_face;
					}
				}
				break;
            case TRI_MAPPING:
				PRINT_DEBUG("-TRI_MAPPING (" << chunk.ID << ',' << chunk.length << ')');
				{
					uint16	nb_vtx;
					*file >> nb_vtx;
					if (read_obj->tcoord == NULL)
						read_obj->tcoord = new float[2 * nb_vtx];
					file->read( (char*)read_obj->tcoord, 2 * (int)sizeof( float ) * nb_vtx );
					for( int i = 0 ; i < nb_vtx ; i++ )
						read_obj->tcoord[ i * 2 + 1 ] = 1.0f - read_obj->tcoord[ i * 2 + 1 ];
				}
				break;
            case TRI_FACEL1:
				PRINT_DEBUG("-TRI_FACEL1 (" << chunk.ID << ',' << chunk.length << ')');
				uint16 nb_index;
				*file >> nb_index;
				read_obj->nb_t_index = short(nb_index * 3);
				read_obj->t_index = new GLushort[nb_index * 3];
				for( int i = 0 ; i < nb_index * 3 ; i += 3 )
				{
					uint16 idx[3];
					*file >> idx[0];
					*file >> idx[1];
					*file >> idx[2];
					read_obj->t_index[i] = idx[0];
					read_obj->t_index[i+1] = idx[1];
					read_obj->t_index[i+2] = idx[2];
					if (read_obj->points)
					{
						Vector3D AB,AC;
						AB = read_obj->points[ read_obj->t_index[ i + 1 ] ] - read_obj->points[ read_obj->t_index[ i ] ];
						AC = read_obj->points[ read_obj->t_index[ i + 2 ] ] - read_obj->points[ read_obj->t_index[ i ] ];
						AB = AB * AC;
						AB.unit();
						read_obj->N[ read_obj->t_index[ i ] ] += AB;
						read_obj->N[ read_obj->t_index[ i + 1 ] ] += AB;
						read_obj->N[ read_obj->t_index[ i + 2 ] ] += AB;
					}
					uint16 face_info;
					*file >> face_info;
				}
				if (read_obj->points)
					for (int i = 0 ; i < read_obj->nb_vtx ; ++i)
						read_obj->N[ i ].unit();
				break;
            case TRI_SMOOTH:
				PRINT_DEBUG("-TRI_SMOOTH (" << chunk.ID << ',' << chunk.length << ')');
				file->seek( file->tell() + chunk.length - 6 );
				break;
            case TRI_LOCAL:
				PRINT_DEBUG("-TRI_LOCAL (" << chunk.ID << ',' << chunk.length << ')');
				*file >> local[0];		// X
				*file >> local[1];		// Y
				*file >> local[2];		// Z
				*file >> local[3];		// local origin
				break;
            case TRI_VISIBLE:
				PRINT_DEBUG("-TRI_VISIBLE (" << chunk.ID << ',' << chunk.length << ')');
				file->seek( file->tell() + chunk.length - 6 );
				break;
            default:
				PRINT_DEBUG("unknown chunk (" << chunk.ID << ',' << chunk.length << ')');
				file->seek( file->tell() + chunk.length - 6 );
			}
		}
예제 #3
0
파일: 3ds.cpp 프로젝트: joaocc/ta3d-git
void Mesh::load3DS(const QString &filename, float scale)
{
	QFile src_3ds(filename);
	src_3ds.open(QFile::ReadOnly);
	if (src_3ds.isOpen())
    {
        destroy();
        QString filepath = filename;
        if (filepath.lastIndexOf("/") != -1)
            filepath = filepath.mid(0, filepath.lastIndexOf("/") + 1);
        else if (filepath.lastIndexOf("\\") != -1)
            filepath = filepath.mid(0, filepath.lastIndexOf("\\") + 1);
        TA3D_3DS_CHUNK_DATA	chunk;
        Mesh *cur_obj = NULL;
        Mesh *read_obj = NULL;
        TA3D_3DS_MATERIAL	*material = NULL;
        Vector3D local[4];
		while (src_3ds.read( (char*)&chunk.ID, sizeof( chunk.ID ) ))
        {
			if (src_3ds.read( (char*)&chunk.length, sizeof( chunk.length ) ) == 0)
				break;
			switch (chunk.ID)
            {
            case MAIN3DS:
                //				printf("MAIN3DS (%d,%d)\n", chunk.ID, chunk.length);
                break;
            case EDIT3DS:
                //					printf("-EDIT3DS (%d,%d)\n", chunk.ID, chunk.length);
                break;
            case EDIT_MATERIAL:
                //						printf("--EDIT_MATERIAL (%d,%d)\n", chunk.ID, chunk.length);
                {
                    TA3D_3DS_MATERIAL	*new_mat = new TA3D_3DS_MATERIAL;
                    new_mat->next = material;
                    material = new_mat;
                }
                break;
            case MAT_NAME:
                //							printf("---MAT_NAME (%d,%d)\n", chunk.ID, chunk.length);
                {
                    QString name = read_ASCIIZ( src_3ds );
                    //								printf( "name = %s\n", name );
					if (material)
                        material->NAME = name;
                }
                break;
            case MAT_AMBIENT:
                //							printf("---MAT_AMBIENT (%d,%d)\n", chunk.ID, chunk.length);
				if (material)
                    read_color_chunk( material->AMBIENT, src_3ds );
                else
					src_3ds.read( chunk.length - 6 );
                break;
            case MAT_DIFFUSE:
                //							printf("---MAT_DIFFUSE (%d,%d)\n", chunk.ID, chunk.length);
				if (material)
                    read_color_chunk( material->DIFFUSE, src_3ds );
                else
					src_3ds.read( chunk.length - 6 );
                break;
            case MAT_SPECULAR:
                //							printf("---MAT_SPECULAR (%d,%d)\n", chunk.ID, chunk.length);
				if (material)
                    read_color_chunk( material->SPECULAR, src_3ds );
                else
					src_3ds.read( chunk.length - 6 );
                break;
            case MAT_SHININESS:
                //							printf("---MAT_SHININESS (%d,%d)\n", chunk.ID, chunk.length);
				if (material)
                    material->SHININESS = read_percent_chunk( src_3ds );
                else
					src_3ds.read( chunk.length - 6 );
                break;
            case MAT_SHIN2PCT:
                //							printf("---MAT_SHIN2PCT (%d,%d)\n", chunk.ID, chunk.length);
				if (material)
                    material->SHIN2PCT = read_percent_chunk( src_3ds );
                else
					src_3ds.read( chunk.length - 6 );
                break;
            case MAT_SHIN3PCT:
                //							printf("---MAT_SHIN3PCT (%d,%d)\n", chunk.ID, chunk.length);
				if (material)
                    material->SHIN3PCT = read_percent_chunk( src_3ds );
                else
					src_3ds.read( chunk.length - 6 );
                break;
            case MAT_TRANSPARENCY:
                //							printf("---MAT_TRANSPARENCY (%d,%d)\n", chunk.ID, chunk.length);
				if (material)
                    material->TRANSPARENCY = read_percent_chunk( src_3ds );
                else
					src_3ds.read( chunk.length - 6 );
                break;
            case MAT_TWO_SIDE:
                //							printf("---MAT_TWO_SIDE (%d,%d)\n", chunk.ID, chunk.length);
				if (material)
                    material->TWO_SIDE = true;
				src_3ds.read( chunk.length - 6 );
                break;
            case MAT_TEXMAP:
                //							printf("---MAT_TEXMAP (%d,%d)\n", chunk.ID, chunk.length);
                if (material)
                {
                    uint16 n_id;
					src_3ds.peek( (char*)&n_id, 2 );
                    if (n_id == MAT_MAPNAME)
                    {
                        material->MAPNAME = read_MAT_MAPNAME_chunk( src_3ds );
                        material->TEXMAP = read_percent_chunk( src_3ds );
                    }
                    else
                    {
                        material->TEXMAP = read_percent_chunk( src_3ds );
                        material->MAPNAME = read_MAT_MAPNAME_chunk( src_3ds );
                    }
                    material->MAPNAME = filepath + material->MAPNAME;
                }
                else
					src_3ds.read( chunk.length - 6 );
                break;
            case EDIT_CONFIG1:
                //						printf("--EDIT_CONFIG1 (%d,%d)\n", chunk.ID, chunk.length);
				src_3ds.read( chunk.length - 6 );
                break;
            case EDIT_CONFIG2:
                //						printf("--EDIT_CONFIG2 (%d,%d)\n", chunk.ID, chunk.length);
				src_3ds.read( chunk.length - 6 );
                break;
            case EDIT_VIEW_P1:
                //						printf("--EDIT_VIEW_P1 (%d,%d)\n", chunk.ID, chunk.length);
				src_3ds.read( chunk.length - 6 );
                break;
            case EDIT_VIEW_P2:
                //						printf("--EDIT_VIEW_P2 (%d,%d)\n", chunk.ID, chunk.length);
				src_3ds.read( chunk.length - 6 );
                break;
            case EDIT_VIEW_P3:
                //						printf("--EDIT_VIEW_P2 (%d,%d)\n", chunk.ID, chunk.length);
				src_3ds.read( chunk.length - 6 );
                break;
            case EDIT_VIEW1:
                //						printf("--EDIT_VIEW1 (%d,%d)\n", chunk.ID, chunk.length);
				src_3ds.read( chunk.length - 6 );
                break;
            case EDIT_BACKGR:
                //						printf("--EDIT_BACKGR (%d,%d)\n", chunk.ID, chunk.length);
				src_3ds.read( chunk.length - 6 );
                break;
            case EDIT_AMBIENT:
                //						printf("--EDIT_AMBIENT (%d,%d)\n", chunk.ID, chunk.length);
				src_3ds.read( chunk.length - 6 );
                break;
            case EDIT_OBJECT:
                //						printf("--EDIT_OBJECT (%d,%d)\n", chunk.ID, chunk.length);
                if (cur_obj)
                {
                    Mesh *n_obj = new Mesh;
                    cur_obj->next = n_obj;
                    cur_obj = n_obj;
                }
                else
                    cur_obj = this;
                cur_obj->type = MESH_TRIANGLES;
                cur_obj->name = read_ASCIIZ( src_3ds );		// Read the object's name
                read_obj = cur_obj;
                break;
            case OBJ_LIGHT:
                //							printf("---OBJ_LIGHT (%d,%d)\n", chunk.ID, chunk.length);
				src_3ds.read( chunk.length - 6 );
                break;
            case OBJ_CAMERA:
                //							printf("---OBJ_CAMERA (%d,%d)\n", chunk.ID, chunk.length);
				src_3ds.read( chunk.length - 6 );
                break;
            case OBJ_UNKNWN01:
                //							printf("---OBJ_UNKNWN01 (%d,%d)\n", chunk.ID, chunk.length);
				src_3ds.read( chunk.length - 6 );
                break;
            case OBJ_UNKNWN02:
                //							printf("---OBJ_UNKNWN02 (%d,%d)\n", chunk.ID, chunk.length);
				src_3ds.read( chunk.length - 6 );
                break;
            case OBJ_TRIMESH:
                //							printf("---OBJ_TRIMESH (%d,%d)\n", chunk.ID, chunk.length);
                if (read_obj->vertex.size() > 0)		// Add a sub object
                {
                    read_obj->child = new Mesh;
                    read_obj = read_obj->child;
                    read_obj->type = MESH_TRIANGLES;
                    read_obj->name = cur_obj->name;
                }
                local[0].x = 1.0f;		local[0].y = 0.0f;		local[0].z = 0.0f;
                local[1].x = 0.0f;		local[1].y = 1.0f;		local[1].z = 0.0f;
                local[2].x = 0.0f;		local[2].y = 0.0f;		local[2].z = 1.0f;
                local[3].x = 0.0f;		local[3].y = 0.0f;		local[3].z = 0.0f;
                break;
            case TRI_VERTEXL:
                {
                    //								printf("----TRI_VERTEXL (%d,%d)\n", chunk.ID, chunk.length);
                    uint16 nb_vtx;
					src_3ds.read( (char*)&nb_vtx, 2 );
                    read_obj->vertex.resize( nb_vtx );
                    read_obj->normal.resize( nb_vtx );
                    if (read_obj->tcoord.isEmpty())
                    {
                        read_obj->tcoord.resize( nb_vtx * 2 );
                        for( int i = 0 ; i < read_obj->vertex.size() ; i++ )
                        {
                            read_obj->tcoord[ i << 1 ] = 0.0f;
                            read_obj->tcoord[ (i << 1) + 1 ] = 0.0f;
                        }
                    }
					src_3ds.read( (char*)read_obj->vertex.data(), sizeof( Vector3D ) * nb_vtx );
                    for( int i = 0 ; i < read_obj->vertex.size() ; i++ )
                    {
                        read_obj->vertex[ i ] = scale * (read_obj->vertex[ i ].x * local[ 0 ] + read_obj->vertex[ i ].y * local[ 1 ] + read_obj->vertex[ i ].z * local[ 2 ] + local[ 3 ]);
                        read_obj->normal[ i ] = Vec();
                    }
                }
                break;
            case TRI_FACEL2:
                //								printf("----TRI_FACEL2 (%d,%d)\n", chunk.ID, chunk.length);
				src_3ds.read( chunk.length - 6 );
                break;
            case TRI_MATERIAL:
                //								printf("----TRI_MATERIAL (%d,%d)\n", chunk.ID, chunk.length);
                {
                    QString material_name = read_ASCIIZ( src_3ds );
                    //									printf("material name = %s\n", material_name );

                    TA3D_3DS_MATERIAL	*cur_mat = (material != NULL) ? material->find( material_name ) : NULL ;

                    if (cur_mat)
                    {
                        //										printf("material found\n");
                        read_obj->flag |= SURFACE_ADVANCED | SURFACE_LIGHTED;
                        if (!cur_mat->MAPNAME.isEmpty())
                        {
                            //											printf("loading texture %s\n", cur_mat->MAPNAME );
                            read_obj->flag |= SURFACE_TEXTURED;
                            read_obj->tex.resize(1);
                            read_obj->tex[0] = Gfx::instance()->loadTexture( cur_mat->MAPNAME.trimmed() );
                        }
                        if (cur_mat->TRANSPARENCY > 0.0f)
                        {
                            read_obj->flag |= SURFACE_BLENDED;
                            read_obj->color = (read_obj->color & 0xFFFFFF00) | (uint32)(cur_mat->TRANSPARENCY * 255);
                        }
                    }
                    else
                        printf("WARNING: material not found!!\n");

                    uint16	nb_faces;
					src_3ds.read( (char*)&nb_faces, 2 );
                    for( int i = 0 ; i < nb_faces ; i++ )
                    {
                        uint16 cur_face;
						src_3ds.read( (char*)&cur_face, 2 );
                    }
                }
                break;
            case TRI_MAPPING:
                //								printf("----TRI_MAPPING (%d,%d)\n", chunk.ID, chunk.length);
                {
                    uint16	nb_vtx;
					src_3ds.read( (char*)&nb_vtx, 2 );
                    read_obj->tcoord.resize(2 * nb_vtx);
					src_3ds.read( (char*)read_obj->tcoord.data(), 2 * sizeof( float ) * nb_vtx );
                    for( int i = 0 ; i < nb_vtx ; i++ )
                        read_obj->tcoord[ i * 2 + 1 ] = 1.0f - read_obj->tcoord[ i * 2 + 1 ];
                }
                break;
            case TRI_FACEL1:
                //								printf("----TRI_FACEL1 (%d,%d)\n", chunk.ID, chunk.length);
                uint16 nb_index;
				src_3ds.read( (char*)&nb_index, 2 );
                read_obj->index.resize(nb_index * 3);
                for( int i = 0 ; i < nb_index * 3 ; i += 3 )
                {
                    uint16 idx[3];
					src_3ds.read( (char*)idx, 2 * 3 );
                    read_obj->index[i] = idx[0];
                    read_obj->index[i+1] = idx[1];
                    read_obj->index[i+2] = idx[2];
                    if (!read_obj->vertex.isEmpty())
                    {
                        Vector3D AB,AC;
                        AB = read_obj->vertex[ read_obj->index[ i + 1 ] ] - read_obj->vertex[ read_obj->index[ i ] ];
                        AC = read_obj->vertex[ read_obj->index[ i + 2 ] ] - read_obj->vertex[ read_obj->index[ i ] ];
                        AB = AB ^ AC;
                        AB.unit();
                        read_obj->normal[ read_obj->index[ i ] ] = read_obj->normal[ read_obj->index[ i ] ] + AB;
                        read_obj->normal[ read_obj->index[ i + 1 ] ] = read_obj->normal[ read_obj->index[ i + 1 ] ] + AB;
                        read_obj->normal[ read_obj->index[ i + 2 ] ] = read_obj->normal[ read_obj->index[ i + 2 ] ] + AB;
                    }
                    uint16 face_info;
					src_3ds.read( (char*)&face_info, 2 );
                }
                if (!read_obj->vertex.isEmpty())
                    for( int i = 0 ; i < read_obj->normal.size() ; i++ )
                        read_obj->normal[ i ].unit();
                break;
            case TRI_SMOOTH:
                //								printf("----TRI_SMOOTH (%d,%d)\n", chunk.ID, chunk.length);
				src_3ds.read( chunk.length - 6 );
                break;
            case TRI_LOCAL:
                //								printf("----TRI_LOCAL (%d,%d)\n", chunk.ID, chunk.length);
				src_3ds.read( (char*)&(local[0]), sizeof( Vector3D ) );		// X
				src_3ds.read( (char*)&(local[1]), sizeof( Vector3D ) );		// Y
				src_3ds.read( (char*)&(local[2]), sizeof( Vector3D ) );		// Z
				src_3ds.read( (char*)&(local[3]), sizeof( Vector3D ) );		// local origin
                break;
            case TRI_VISIBLE:
                //								printf("----TRI_VISIBLE (%d,%d)\n", chunk.ID, chunk.length);
				src_3ds.read( chunk.length - 6 );
                break;
            default:
                //				printf("unknown (%d,%d)\n", chunk.ID, chunk.length);
				src_3ds.read( chunk.length - 6 );
            }
        }
        if (material)
            delete material;
		src_3ds.close();

        computeInfo();
        emit loaded();
    }
}