I just whipped this up in a few minutes. It handles quads and polygons. I did not bother with materials, and the way it is used here is slightly different from the LoadMesh() convention:
Function LoadObj:Int(file:String,surf:TSurface) Local stream:TStream Local position:TBank=New TBank Local normal:TBank=New TBank Local texcoords:TBank=New TBank Local line:String[] Local indices:String[] Local sumindices:Int Local x#,y#,z#,s$,a,b,c,na,nb,nc Local nx#,ny#,nz#,tu#,tv#,v,m# Local currentsmoothgroup Local face:TObjFace,vert:TObjVert,face2:TObjFace Local n,avg#,n2 stream=ReadFile(file) If Not stream Return While Not stream.Eof() s$=Trim(stream.ReadLine()) If s="" Continue If Left(s,1)="#" Continue line=s.split("") If line.length=0 Continue Select Lower(line[0]) Case "v" If line.length<3 Return AppendFloat position,Float(line[1]) AppendFloat position,Float(line[2]) AppendFloat position,Float(line[3]) Case "vt" If line.length<2 Return AppendFloat texcoords,Float(line[1]) AppendFloat texcoords,-Float(line[2]) Case "vn" If line.length<3 Return nx=Float(line[1]) ny=Float(line[2]) nz=Float(line[3]) m=Sqr(nx*nx+ny*ny+nz*nz) nx:/m ny:/m nz:/m AppendFloat normal,nx AppendFloat normal,ny AppendFloat normal,nz Case "s" If line.length>1 currentsmoothgroup=Int(line[1]) EndIf Case "f" Local indice[line.length-1] Local verts:TObjVert[indice.length] face=New TObjFace face.verts=verts face.smoothgroup=currentsmoothgroup For n=0 To indice.length-1 indices=line[n+1].split("/") tu=0 tv=0 nx=0 ny=0 nz=0 vert=New TObjVert v=Int(indices[0])-1 x#=position.PeekFloat(v*12+0) y#=position.PeekFloat(v*12+4) z#=position.PeekFloat(v*12+8) If indices.length>1 v=Int(indices[1])-1 tu#=texcoords.PeekFloat(v*8+0) tv#=texcoords.PeekFloat(v*8+4) If indices.length>2 v=Int(indices[2])-1 nx#=normal.PeekFloat(v*12+0) ny#=normal.PeekFloat(v*12+4) nz#=normal.PeekFloat(v*12+8) vert.normalsdefined=True EndIf EndIf vert.x=x vert.y=y vert.z=z vert.nx=nx vert.ny=ny vert.nz=nz vert.u=tu vert.v=tv face.verts[n]=vert Next 'For Local n=2 To indice.length-1 ' surf.addtriangle indice[n],indice[0],indice[n-1] ' sumindices:+3 'Next EndSelect Wend 'Calculate face normals For face=EachIn TObjFace.list If face.verts.length<3 Continue TriangleNormal(face.verts[0].x,face.verts[0].y,face.verts[0].z,face.verts[1].x,face.verts[1].y,face.verts[1].z,face.verts[2].x,face.verts[2].y,face.verts[2].z) face.nx=vector_x face.ny=vector_y face.nz=vector_z For n=0 To face.verts.length-1 If Not face.verts[n].normalsdefined ' use hard edges for verts with undefined normal face.verts[n].nx=face.nx face.verts[n].ny=face.ny face.verts[n].nz=face.nz EndIf Next Next For face=EachIn TObjFace.list If face.smoothgroup For n=0 To face.verts.length-1 nx#=face.nx ny#=face.ny nz#=face.nz avg#=1.0 For face2=EachIn TObjFace.list' this part is highly inefficient, but don't give a fuck If face=face2 Continue If face.smoothgroup<>face2.smoothgroup Continue For n2=0 To face2.verts.length-1 If Abs(face.verts[n].x-face2.verts[n2].x)>0.01 Continue If Abs(face.verts[n].y-face2.verts[n2].y)>0.01 Continue If Abs(face.verts[n].z-face2.verts[n2].z)>0.01 Continue nx:+face2.nx ny:+face2.ny nz:+face2.nz avg:+1 n2=face2.verts.length-1 Next Next face.verts[n].nx=nx/avg face.verts[n].ny=ny/avg face.verts[n].nz=nz/avg Next EndIf Next 'Add triangles For face=EachIn TObjFace.list For n=0 To face.verts.length-1 face.verts[n].index=surf.FindVertex(face.verts[n].x,face.verts[n].y,face.verts[n].z,face.verts[n].nx,face.verts[n].ny,face.verts[n].nz,face.verts[n].u,face.verts[n].v) If n>1 surf.addtriangle face.verts[n].index,face.verts[0].index,face.verts[n-1].index sumindices:+3 EndIf Next Next Return sumindices+1 EndFunction Type TObjVert Field x#,y#,z# Field nx#,ny#,nz# Field u#,v# Field index Field normalsdefined EndType Type TObjFace Global list:TList=New TList Method New() list.addfirst(Self) EndMethod Field nx#,ny#,nz# Field verts:TObjVert[] Field smoothgroup EndType Global VECTOR_x# Global VECTOR_y# Global VECTOR_z# Function TriangleNormal(Ax#,Ay#,Az#,Bx#,By#,Bz#,Cx#,Cy#,Cz#) Local ux#,uy#,uz#,vx#,vy#,vz#,vec:TVec4 ux#=bx-ax uy#=by-ay uz#=bz-az vx#=cx-bx vy#=cy-by vz#=cz-bz VECTOR_x=uy#*vz#-uz#*vy# VECTOR_y=uz#*vx#-ux#*vz# VECTOR_z=ux#*vy#-uy#*vx# Local m#=Sqr(VECTOR_x*VECTOR_x+VECTOR_y*VECTOR_y+VECTOR_z*VECTOR_z) VECTOR_x:/m VECTOR_y:/m VECTOR_z:/m EndFunction