Example #1
0
void tlink(void) {
    int i;
    FILE *fp;

    if ( ( obj_file_cnt() + lib_file_cnt() ) > 0 ) {
        if ( get_dosex() != OPT_PMODE )
            fprintf( stderr, "TLINK use only with PMODE!\n" );
        fp = response( RESPONSE );
        fprintf( fp, "/3/c/d%s%s", 
            get_option(OPT_MAPFILE) ? "/m/l/s" : "/x",
            get_option(OPT_DEBUG) ? "/v" : ""
        );
        if ( lib_file_cnt() > 0 )
            fprintf(fp, "/L%s ", get_lib_path() );
        if (! get_option(OPT_NODEFLIB) ) {
            if ( get_option(OPT_DEBUG) )
                fprintf(fp,"%s\\C0DOSD.OBJ", get_syslib_path() );
            else
                fprintf(fp,"%s\\C0DOS.OBJ", get_syslib_path() );
        }
        for ( i = 0; i < obj_file_cnt(); i++ )
            fprintf( fp, " %s", obj_file(i) );
        fprintf( fp, ",%s,%s,",  
            get_exe_name(),
            get_option( OPT_MAPFILE) ? get_exe_name() : "NUL"
        );
        if (! get_option(OPT_NODEFLIB) )
            fprintf(fp,"%s\\CLDOS.LIB", get_syslib_path() );
        for ( i = 0; i < lib_file_cnt(); i++ )
            fprintf( fp, " %s", lib_file(i) );
        fprintf( fp, "\n" );
        fclose(fp);
        exec("TLINK", "@" RESPONSE );					
        if (! get_option(OPT_KEEPRSP) )
            unlink( RESPONSE );
    }
}
Example #2
0
/**
 * @brief Writes the given Mesh to an obj file that for example can be read by Meshlab.
 *
 * If the mesh contains vertex colour information, it will be written to the obj as well.
 *
 * @param[in] mesh The mesh to save as obj.
 * @param[in] filename Output filename.
 */
inline void write_obj(Mesh mesh, std::string filename)
{
    assert(mesh.vertices.size() == mesh.colors.size() || mesh.colors.empty());

    std::ofstream obj_file(filename);

    if (mesh.colors.empty()) {
        for (std::size_t i = 0; i < mesh.vertices.size(); ++i) {
            obj_file << "v " << mesh.vertices[i][0] << " " << mesh.vertices[i][1] << " " << mesh.vertices[i][2] << " " << std::endl;
        }
    }
    else {
        for (std::size_t i = 0; i < mesh.vertices.size(); ++i) {
            obj_file << "v " << mesh.vertices[i][0] << " " << mesh.vertices[i][1] << " " << mesh.vertices[i][2] << " " << mesh.colors[i][0] << " " << mesh.colors[i][1] << " " << mesh.colors[i][2] << " " << std::endl;
        }
    }

    for (auto&& v : mesh.tvi) {
        // Add one because obj starts counting triangle indices at 1
        obj_file << "f " << v[0] + 1 << " " << v[1] + 1 << " " << v[2] + 1 << std::endl;
    }

    return;
}
/**
* Load the vertex and normal information from a obj file
* - Clears current information from model
* - Currently only supports objs that have one mesh and ignore material of mesh (must be set up somewhere else
* - Currently loads face based normals
* @param filename (name of obj file)
* @param Model (model to load information);
* @return bool (if file exists)
**/
bool init_model_from_obj(const wchar_t *filename, Model *model){
	// Is the model init'd?
	if (model == NULL)
		return false;

	std::ifstream obj_file(filename);

	//Check if file exists
	if (!obj_file) {
		debug.write("Failed to open file");
		return false;
	}
	
	//std::vector<vec2> vertex_texture;
	//std::vector<vec4> vertex_normal;

	float x, y, z, w;
	int a, b, c, d, e, f, g, h, i;
	std::string line;
	unsigned int color = 0xffff00;

	while (getline(obj_file, line)) {
		// Found new vertex
		if (line[0] == 'c' && line[1] == ' ') {
			sscanf_s(&line[0], "c 0x%x", &color);
		}
		if (line[0] == 'v' && line[1] == ' '){
			sscanf_s(&line[0], "v %f %f %f %f", &x, &y, &z, &w);
			model->verts4D.push_back({ x, y, z, w, color});
			model->verts2.push_back({ x,y,z,color });
		}
		// Found new texture mapping coord
		/*else if (line[0] == 'v' && line[1] == 't'){
			sscanf_s(&line[0], "vt %f %f", &x, &y);
			vertex_texture.push_back(Vector2f( x, 1.0f - y ));
		}*/
		// Found new normal
		/*else if (line[0] == 'v' && line[1] == 'n'){
			sscanf_s(&line[0], "vn %f %f %f %f", &x, &y, &z, &w);
			vertex_normal.push_back({ x, y, z, w });
		}*/
		// Found new face
		else if (line[0] == 'f'){
			sscanf_s(&line[0], "f %d//%d %d//%d %d//%d", &a, &g, &b, &h, &c, &i);
			model->indices.push_back((a - 1));

			//model->verts[(a - 1)].tU = vertex_texture[(d - 1)](0);
			//model->verts[(a - 1)].tV = vertex_texture[(d - 1)](1);

			/*model->verts[(a - 1)].nX = vertex_normal[(g - 1)](0);
			model->verts[(a - 1)].nY = vertex_normal[(g - 1)](1);
			model->verts[(a - 1)].nZ = vertex_normal[(g - 1)](2);
			model->verts[(a - 1)].nW = vertex_normal[(g - 1)](3);*/

			model->indices.push_back((c - 1));


			//model->verts[(c - 1)].tU = vertex_texture[(f - 1)](0);
			//model->verts[(c - 1)].tV = vertex_texture[(f - 1)](1);

			/*model->verts[(c - 1)].nX = vertex_normal[(i - 1)](0);
			model->verts[(c - 1)].nY = vertex_normal[(i - 1)](1);
			model->verts[(c - 1)].nZ = vertex_normal[(i - 1)](2);
			model->verts[(c - 1)].nW = vertex_normal[(i - 1)](3);*/

			model->indices.push_back((b - 1));

			//model->verts[(b - 1)].tU = vertex_texture[(e - 1)](0);
			//model->verts[(b - 1)].tV = vertex_texture[(e - 1)](1);

			/*model->verts[(b - 1)].nX = vertex_normal[(h - 1)](0);
			model->verts[(b - 1)].nY = vertex_normal[(h - 1)](1);
			model->verts[(b - 1)].nZ = vertex_normal[(h - 1)](2);
			model->verts[(b - 1)].nW = vertex_normal[(h - 1)](3);*/
		}
	}
	return true;
}
Example #4
0
void ModelObject::read_obj(const char * filename)
{
    int vert_id = 1;
    std::string temp;
    std::string obj_line;
    std::ifstream obj_file (filename);

    if (obj_file.is_open()) {
        while (getline(obj_file, obj_line)) {
            if (obj_line[0] == 'v') {
                std::istringstream vert_string (obj_line);
                coord * new_coord = new coord;

                new_coord->id = vert_id;

                for (int i = 0; i < 4; i++) {
                    if (getline(vert_string, temp, ' ')) {
                        if (i == 1) {
                            new_coord->x = (float)atof(temp.c_str());
                        }
                        else if (i == 2) {
                            new_coord->y = (float)atof(temp.c_str());
                        }
                        else if (i == 3) {
                            new_coord->z = (float)atof(temp.c_str());
                        }
                    }
                }

                object->vertices.push_back(new_coord);
                object->vert_count++;
                vert_id++;
            }
            else if (obj_line[0] == 'f') {
                object->face_count++;

                std::istringstream face_string (obj_line);
                face * new_face = new face;
                int coord_id;

                getline(face_string, temp, ' ');

                while (getline(face_string, temp, ' '))
                {
                    coord_id = (int)atoi(temp.c_str());

                    new_face->coords.push_back(object->vertices[coord_id - 1]);
                }

                object->faces.push_back(new_face);

            }
            else if (obj_line[0] == 'o' && object->obj_name == 0) {
                std::string name_string (obj_line);

                if (name_string.length() > 2) {
                    object->obj_name = new char[name_string.length() - 1];
                    
                    for (int i = 2; i < name_string.length(); i++)
                        object->obj_name[i - 2] = name_string[i];
                }
            }
        }
        obj_file.close();

        process_object();
    }
}
bool mesh_3D::load_obj(string filename)
  {
    ifstream obj_file(filename.c_str());
    string line;
    float obj_line_data[4][3];
    point_3D helper_point;

    vector<point_3D> normals;
    vector<point_3D> texture_vertices;

    if (!obj_file.is_open())
      return false;

    this->vertices.clear();
    this->triangle_indices.clear();

    while (getline(obj_file,line))
      {
        switch (line[0])
          {
            case 'v':
              if (line[1] == 'n')        // normal vertex
                {
                  parse_obj_line(line,obj_line_data);

                  helper_point.x = obj_line_data[0][0];
                  helper_point.y = obj_line_data[1][0];
                  helper_point.z = obj_line_data[2][0];

                  normals.push_back(helper_point);
                  break;
                }
              else if (line[1] == 't')   // texture vertex
                {
                  parse_obj_line(line,obj_line_data);

                  helper_point.x = obj_line_data[0][0];
                  helper_point.y = obj_line_data[1][0];
                  helper_point.z = obj_line_data[2][0];

                  texture_vertices.push_back(helper_point);
                  break;
                }
              else                       // position vertex
                {
                  parse_obj_line(line,obj_line_data);
                  vertex_3D vertex;

                  vertex.position.x = obj_line_data[0][0];
                  vertex.position.y = obj_line_data[1][0];
                  vertex.position.z = obj_line_data[2][0];

                  this->vertices.push_back(vertex);

                  break;
                }

            case 'f':
              unsigned int indices[4],i,faces;
              parse_obj_line(line,obj_line_data);

              for (i = 0; i < 4; i++)     // triangle indices
                indices[i] = floor(obj_line_data[i][0]) - 1;

              if (obj_line_data[3][0] < 0.0)
                {
                  this->triangle_indices.push_back(indices[0]);
                  this->triangle_indices.push_back(indices[1]);
                  this->triangle_indices.push_back(indices[2]);

                  faces = 3;     // 3 vertex face
                }
              else
                {
                  this->triangle_indices.push_back(indices[0]);
                  this->triangle_indices.push_back(indices[1]);
                  this->triangle_indices.push_back(indices[2]);

                  this->triangle_indices.push_back(indices[0]);
                  this->triangle_indices.push_back(indices[2]);
                  this->triangle_indices.push_back(indices[3]);

                  faces = 4;     // 4 vertex face
                }

              int vt_index, vn_index;

              for (i = 0; i < faces; i++)    // texture coordinates and normals
                {
                  vt_index = floor(obj_line_data[i][1]) - 1;
                  vn_index = floor(obj_line_data[i][2]) - 1;

                  if (indices[i] >= this->vertices.size() || vt_index >= (int) texture_vertices.size() || vt_index < 0)
                    continue;

                  this->vertices[indices[i]].texture_coords[0] = texture_vertices[vt_index].x;
                  this->vertices[indices[i]].texture_coords[1] = texture_vertices[vt_index].y;
                  this->vertices[indices[i]].texture_coords[2] = texture_vertices[vt_index].z;

                  if (vn_index >= (int) normals.size() || vn_index < 0)
                    continue;

                  this->vertices[indices[i]].normal.x = normals[vn_index].x;
                  this->vertices[indices[i]].normal.y = normals[vn_index].y;
                  this->vertices[indices[i]].normal.z = normals[vn_index].z;
                }
              break;

            default:
              break;
          }
      }

    obj_file.close();
    this->update_bounding_sphere();
    return true;
  }
Example #6
0
void valx(void) {
    int i;
    FILE *fp;
    char *c0 = "C0DOS.OBJ";
    char *c0d= "C0DOSD.OBJ";
    char *cl = "CLDOS.LIB";
    char *ci = NULL;
    char *dosx = NULL;
   char *lnk_op = "/NCI /32";


    if ( ( obj_file_cnt() + lib_file_cnt() ) > 0 ) {
        int sys = get_dosex();
        switch ( sys ) {
            case OPT_W32CON:
                c0d = c0 = "C0xwin.obj"; cl = "CLWIN.LIB"; ci = "CLIMP.LIB"; 
                lnk_op = "/NCI /PE";
                break;
            case OPT_W32GUI:
                c0d = c0 = "C0win.obj"; cl = "CLWIN.LIB"; ci = "CLIMP.LIB"; 
                lnk_op = "/NCI /PE /WIN";
                break;
            case OPT_W32DLL: 
                c0d = c0 = "C0dwin.obj"; cl = "CLWIN.LIB"; ci = "CLIMP.LIB";
                lnk_op = "/NCI /PE /BDL";
                break;
         case OPT_DOS32A:
            c0d = "c0doswd.obj" ;
            c0 = "c0dosw.obj" ;
            lnk_op = "/NCI /LE" ;
            dosx = "stub32a.exe" ;
            break ;
            case OPT_PMODEW:
                c0d = "c0doswd.obj" ;
                c0 = "c0dosw.obj" ;
                lnk_op = "/NCI /LE" ;
                dosx = "pmodew.exe"; 
                break;
            case OPT_DOS4G:	
                c0d = "c0doswd.obj" ;
                c0 = "c0dosw.obj" ;
                lnk_op = "/NCI /LE" ;
                dosx = "4gstub.exe"; 
                break;
            case OPT_WDOSX:	
                c0d = "c0doswd.obj" ;
                c0 = "c0dosw.obj" ;
                lnk_op = "/NCI /LE" ;
                dosx = "wdosxle.exe"; 
                break;
            case OPT_ZRDX:	
                c0d = "c0doswd.obj" ;
                c0 = "c0dosw.obj" ;
                lnk_op = "/NCI /LE" ;
                dosx = "zrdx.exe"; 
                break;
            case OPT_CAUSEWAY:	
                c0d = "c0doswd.obj" ;
                c0 = "c0dosw.obj" ;
                lnk_op = "/NCI /LE" ;
                dosx = "cwstub.exe"; 
                break;
            case OPT_HXDOS:
                c0d = c0 = "C0xwin.obj"; 
                cl = "CLWIN.LIB"; 
                ci = "CLIMP.LIB"; 
                lnk_op = "/NCI /PE";
                dosx = "dpmist32.bin";
                break;
            case OPT_WHXDOS:
                c0d = c0 = "C0doswhx.obj"; 
                lnk_op = "/NCI /PE";
                dosx = "hdld32.bin";
                break;
            case OPT_D3X:
                c0d = "c0doswd.obj";
                c0 = "c0dos.obj";
                lnk_op = "/NCI /LE" ;
                dosx = "d3xw.exe"; 
                break;
            default:
                fprintf( stderr, "VALX use only with PMODE!\n" );
            case OPT_PMODE:
                break;
        }
        fp = response( RESPONSE );
        fprintf( fp, "-NOCA -USE32 %s ",
            get_option(OPT_MAPFILE) ? "-MAP" : "-NOMAP" );	
        if ( lnk_op )
            fprintf( fp, "%s ", lnk_op);
        if (dosx)
            fprintf(fp, "-STB:(%s\\%s) ", get_syslib_path(), dosx);
        if (! get_option(OPT_NODEFLIB) ) {
            if ( get_option(OPT_DEBUG) )
            fprintf(fp,"\"%s\\%s\"", get_syslib_path(), c0d );
            else
            fprintf(fp,"\"%s\\%s\"", get_syslib_path(), c0 );
        }
        for ( i = 0; i < obj_file_cnt(); i++ )
            fprintf( fp, " %s", obj_file(i) );
        fprintf( fp, ",%s,%s,",  
            get_exe_name(),
            get_option( OPT_MAPFILE) ? get_exe_name() : "NUL"
        );
        if (! get_option(OPT_NODEFLIB) )
         fprintf(fp,"\"%s\\%s\"", get_syslib_path(), cl );
        if (ci)
         fprintf(fp," \"%s\\%s\"", get_syslib_path(), ci );
        for ( i = 0; i < lib_file_cnt(); i++ )
            fprintf( fp, " %s", lib_file(i) );
        fprintf( fp, "\n" );
        for ( i = 0; i < res_file_cnt(); i++ )
            fprintf( fp, " %s", res_file(i) );
        fprintf( fp, "\n\n" );
        fclose(fp);
        exec("VALX", "@" RESPONSE );
        if (! get_option(OPT_KEEPRSP) )
            unlink( RESPONSE );
          if ( !get_option(OPT_KEEPGEN) )
        {
            del_res_tmpfiles();
        }
        if (sys == OPT_WHXDOS)
        {
            exec("PATCHPE", get_exe_name());
        }
    }
}
Example #7
0
void olink(void) {
    int i;
    FILE *fp;
    char *c0 = "c0pm.o";
    char *c0d= "c0pmd.o";
    char *cl = "cldos.l";
    char *ci = NULL;
   char *lnk_op = "/T:PM";


    if ( ( obj_file_cnt() + lib_file_cnt() ) > 0 ) {
        int sys = get_dosex();
        switch ( sys ) {
            case OPT_W32CON:
                c0d = c0 = "c0xpe.o"; cl = "clwin.l"; ci = "climp.l"; 
                lnk_op = "/T:CON32";
                break;
            case OPT_W32GUI:
                c0d = c0 = "c0pe.o"; cl = "clwin.l"; ci = "climp.l"; 
                lnk_op = "/T:GUI32";
                break;
            case OPT_W32DLL: 
                c0d = c0 = "c0dpe.o"; cl = "clwin.l"; ci = "climp.l";
                lnk_op = "/T:DLL32";
                break;
         case OPT_DOS32A:
            c0d = "c0watd.o" ;
            c0 = "c0wat.o" ;
            lnk_op = "/T:DOS32;sstub32a.exe" ;
            break ;
            case OPT_PMODEW:
            c0d = "c0watd.o" ;
            c0 = "c0wat.o" ;
            lnk_op = "/T:DOS32;spmodew.exe" ;
                break;
            case OPT_DOS4G:	
            c0d = "c0watd.o" ;
            c0 = "c0wat.o" ;
            lnk_op = "/T:DOS32;s4gstub.exe" ;
                break;
            case OPT_WDOSX:	
            c0d = "c0watd.o" ;
            c0 = "c0wat.o" ;
            lnk_op = "/T:DOS32;swdosxle.exe" ;
                break;
            case OPT_ZRDX:	
            c0d = "c0watd.o" ;
            c0 = "c0wat.o" ;
            lnk_op = "/T:DOS32;szrdx.exe" ;
                break;
            case OPT_CAUSEWAY:	
            c0d = "c0watd.o" ;
            c0 = "c0wat.o" ;
            lnk_op = "/T:DOS32;scwstub.exe" ;
                break;
            case OPT_HXDOS:
                c0d = c0 = "c0xpe.o"; 
                cl = "CLWIN.L"; 
                ci = "CLIMP.L"; 
                lnk_op = "/T:CON32;sdpmist32.bin";
                break;
            case OPT_WHXDOS:
                c0d = "c0hxd.o";
                c0 = "c0hx.o"; 
                lnk_op = "/T:CON32;shdld32.bin /DOBJECTALIGN=10000";
                break;
            case OPT_D3X:
            c0d = "c0watd.o" ;
            c0 = "c0wat.o" ;
            lnk_op = "/T:DOS32;sd3xw.exe" ;
                break;
            default:
                fprintf( stderr, "VALX use only with PMODE!\n" );
            case OPT_PMODE:
                break;
        }
        fp = response( RESPONSE );
        fprintf( fp, "-c%s",
            get_option(OPT_MAPFILE) ? " -m" : "" );	
        fprintf( fp, " -o%s%s", get_exe_name(),	get_option( OPT_MAPFILE) ? get_exe_name() : "");
        if ( lnk_op )
        {
            fprintf( fp, " %s", lnk_op);
        }
        if (! get_option(OPT_NODEFLIB) ) {
            if ( get_option(OPT_DEBUG) )
            fprintf(fp," \"%s\\%s\"", get_syslib_path(), c0d );
            else
            fprintf(fp," \"%s\\%s\"", get_syslib_path(), c0 );
        }
        for ( i = 0; i < obj_file_cnt(); i++ )
            fprintf( fp, " %s", obj_file(i) );
        for ( i = 0; i < lib_file_cnt(); i++ )
            fprintf( fp, " %s", lib_file(i) );
        if (! get_option(OPT_NODEFLIB) )
        {
            if (cl)
            {
                 fprintf(fp," \"%s\\%s\"", get_syslib_path(), cl );
            }
            if (ci)
            {
                 fprintf(fp," \"%s\\%s\"", get_syslib_path(), ci );
            }
        }
        for ( i = 0; i < res_file_cnt(); i++ )
            fprintf( fp, " %s", res_file(i) );
        fclose(fp);
        exec("olink", "@" RESPONSE );
        if (! get_option(OPT_KEEPRSP) )
            unlink( RESPONSE );
          if ( !get_option(OPT_KEEPGEN) )
        {
            del_res_tmpfiles();
        }
        if (sys == OPT_WHXDOS)
        {
            exec("PATCHPE", get_exe_name());
        }
    }
}
Example #8
0
void geometry_file::load_wavefront( const crap::string256& filename )
{
	crap::file obj_file( DATA_PATH + filename );
	size_t32 file_size = (size_t32)obj_file.size();
	u8* buffer = (u8*) _content_pool->allocate( file_size );
	obj_file.read_bytes( buffer, file_size );
	obj_file.close();

	u32 count_vertices = 0;
	u32 count_uvs = 0;
	u32 count_normals = 0;
	u32 count_faces = 0;
	u32 count_groups = 0;
	u32 count_material_groups = 0;

	//count content
	b8 newline = true;
	for( int i = 0; i< obj_file.size(); ++i )
	{
		if( newline )
		{
			newline = false;

			switch( buffer[i] )
			{
			case '#':
				{
					//comment
					break;
				}

			case 'v':
				{
					if( buffer[ i+1 ] == 't' )
						++_uvs_index;
					else if( buffer[ i+1 ] == 'n' )
						++_normals_index;
					else if( buffer[ i+1 ] == ' ' )
						++_vertices_index;

					break;
				}

			case 'f':
				{
					++_face_index;

					break;
				}

			case 'g':
				{
					++_group_index;

					break;
				}

			case 'u':
				{
					if( buffer[i+1] == 's' && buffer[i+2] == 'e' && buffer[i+3] == 'm' && buffer[i+4] == 't' && buffer[i+5] == 'l' )
						++_material_index;

					break;
				}

			default:
				{}
			}
		}
		
		if( buffer[i] == '\n' )
			newline = true;
	}

	if( _vertices_index != 0 )
		_vertices = (crap::vector3f*)_content_pool->allocate( _vertices_index * sizeof(crap::vector3f) );

	if( _uvs_index != 0 )
		_uvs = (crap::vector2f*)_content_pool->allocate( _uvs_index * sizeof(crap::vector2f) );

	if( _normals_index != 0 )
		_normals = (crap::vector3f*)_content_pool->allocate( _normals_index * sizeof(crap::vector3f) );

	if( _face_index != 0 )
		_faces = (face*)_content_pool->allocate( _face_index * sizeof(face) );

	if( _group_index != 0 )
		_groups = (group*)_content_pool->allocate( _group_index * sizeof(group) );

	if( _material_index != 0 )
		_material_groups = (material_group*)_content_pool->allocate( _material_index * sizeof(material_group) );

	newline = true;
	for( int i = 0; i< obj_file.size(); ++i )
	{
		if( newline )
		{
			newline = false;

			switch( buffer[i] )
			{
			case '#':
				{
					//comment
					break;
				}

			case 'v':
				{
					if( buffer[ i+1 ] == 't' )
					{
						crap::vector2f uv_vec;
						sscanf( (const char*)buffer+i+3, "%f %f", &uv_vec.x, &uv_vec.y );
						uv_vec.y *= -1;
						_uvs[ count_uvs++ ] = uv_vec;
					}
					else if( buffer[ i+1 ] == 'n' )
					{
						crap::vector3f norm_vec;
						sscanf( (const char*)buffer+i+3, "%f %f %f", &norm_vec.x, &norm_vec.y, &norm_vec.z );
						_normals[ count_normals++ ] = norm_vec;
					}
					else if( buffer[ i+1 ] == ' ' )
					{
						crap::vector3f vert_vec;
						sscanf( (const char*)buffer+i+2, "%f %f %f", &vert_vec.x, &vert_vec.y, &vert_vec.z );
						_vertices[ count_vertices++ ] = vert_vec;
					}

					break;
				}

			case 'f':
				{
					face tmp_face;
					sscanf( (const char*)buffer+i+2, "%i/%i/%i %i/%i/%i %i/%i/%i", 
						&(tmp_face.vertices[0]), &(tmp_face.uvs[0]), &(tmp_face.normals[0]),
						&(tmp_face.vertices[1]), &(tmp_face.uvs[1]), &(tmp_face.normals[1]),
						&(tmp_face.vertices[2]), &(tmp_face.uvs[2]), &(tmp_face.normals[2]) );
					_faces[ count_faces++ ] = tmp_face;

					break;
				}

			case 'g':
				{
					if( _groups[count_groups].index_start != -1 )
						_groups[ count_groups++ ].index_end = count_faces;
					else
						_groups[count_groups].index_start = count_faces;

					break;
				}

			case 'u':
				{
					if( buffer[i+1] == 's' && buffer[i+2] == 'e' && buffer[i+3] == 'm' && buffer[i+4] == 't' && buffer[i+5] == 'l' )
					{
						if( _material_groups[ count_material_groups ].index_start != -1 )
							_material_groups[ count_material_groups++ ].index_end = count_faces;
						else
							_material_groups[ count_material_groups ].index_start = count_faces;
					}

					break;
				}

			default:
				{}
			}
		}
		
		if( buffer[i] == '\n' )
			newline = true;
	}
	if( count_groups != 0 && _groups[count_groups].index_end == -1 )
		_groups[ count_groups ].index_end = count_faces;

	if( count_material_groups != 0 && _material_groups[ count_material_groups ].index_end == -1 )
		_material_groups[ count_material_groups ].index_end = count_faces;
}