Simple .obj mesh reader for MATLAB

Alec Jacobson

March 08, 2010

weblog/

matlab obj mesh reader screenshotI wrote a little .obj file format reader in MATLAB. It only reads the vertices and faces of a triangle mesh (ignoring all the other commands and features). I use it to extract the vertex and face arrays. Here's the code, I save it in a file called read_vertices_and_faces_from_obj_file.m:

function [V,F] = read_vertices_and_faces_from_obj_file(filename)
  % Reads a .obj mesh file and outputs the vertex and face list
  % assumes a 3D triangle mesh and ignores everything but:
  % v x y z and f i j k lines
  % Input:
  %  filename  string of obj file's path
  %
  % Output:
  %  V  number of vertices x 3 array of vertex positions
  %  F  number of faces x 3 array of face indices
  %
  V = zeros(0,3);
  F = zeros(0,3);
  vertex_index = 1;
  face_index = 1;
  fid = fopen(filename,'rt');
  line = fgets(fid);
  while ischar(line)
    vertex = sscanf(line,'v %f %f %f');
    face = sscanf(line,'f %d %d %d');
    face_long = sscanf(line,'f %d//%d %d//%d %d//%d',6);
    face_long_long = sscanf(line,'f %d/%d/%d %d/%d/%d %d/%d/%d',9);

    % see if line is vertex command if so add to vertices
    if(size(vertex)>0)
      V(vertex_index,:) = vertex;
      vertex_index = vertex_index+1;
   % see if line is simple face command if so add to faces
    elseif(size(face,1)==3)
      F(face_index,:) = face;
      face_index = face_index+1;
    % see if line is a face with normal indices command if so add to faces
    elseif(size(face_long,1)==6)
      % remove normal
      face_long = face_long(1:2:end);
      F(face_index,:) = face_long;
      face_index = face_index+1;
    % see if line is a face with normal and texture indices command if so add to faces
    elseif(size(face_long_long,1)==9)
      % remove normal and texture indices
      face_long_long = face_long_long(1:3:end);
      F(face_index,:) = face_long_long;
      face_index = face_index+1;
    else
      fprintf('Ignored: %s',line);
    end

    line = fgets(fid);
  end
  fclose(fid);
end

Then I can read and render a mesh with phong shading:

[V,F] = read_vertices_and_faces_from_obj_file('path/to/your/mesh.obj');
trisurf(F,V(:,1),V(:,2),V(:,3),'FaceColor',[0.26,0.33,1.0 ]);
light('Position',[-1.0,-1.0,100.0],'Style','infinite');
lighting phong;

Update: I changed the above to account for other triangle face lines (as per Limdor's comment). However, there is a much fuller version available in my qptoolbox and the libigl tutorial shows how to create a readOBJ using C++ via a mex function which results in much faster loading times for big meshes.