It is currently Sat Sep 23, 2017 5:27 pm

All times are UTC + 1 hour




Post new topic Reply to topic  [ 9 posts ] 
Author Message
 Post subject: wavefront OBJ files Loader
PostPosted: Wed May 03, 2017 7:09 am 
Offline
Addict
Addict

Joined: Sun Jun 25, 2006 7:28 pm
Posts: 1255
a basic OBJ reader will read coordinates of vertex, normal, textures and indices. it does not read the associated material files sometimes associated with OBJ files
test it with any Obj file you have or with these collection of OBJ files
Righ click to be able to click on the button to read another OBJ file
http://wikisend.com/download/980832/OBJ_Loader.7z
Or
http://www.mediafire.com/file/hgcn6rdso ... _Loader.7z

try to load hairball.obj from
http://graphics.williams.edu/data/meshes.xml
it is a gigantic mesh (200 MB) with Triangles: 2,880,000 and Vertices: 1,441,098 but the program will read a part of the mesh to be able to view acceptable hairball in 15 seconds on my computer

Image
the first demo use Lines (#PB_Mesh_LineList) so it will show the polygons such as Quads, look the woman.obj inside OBJ_Loader.7z package
EDITED:: added remove the double spaces in some OBJ files.
Code:
;DisableDebugger
Global CameraSpeed.f = 0.02

Declare ParseString(st.s)
Declare MakeMesh()
Declare ChangeMesh()

Global Dim MeshData.PB_MeshVertex(0) ; for centering the mesh only

Define.f KeyX, KeyY, MouseX, MouseY
Quit.b = #False
#but = 10

Global.s path
Define.f x, y, z, nx, ny, nz, u, v
Global vert.l
Global tri.l, i.l, IndicesPerLine.l
Global st.s
Global.f NormX, NormY, NormZ
Global IndicesPerLine
Global vertices = 0
tri = 0
vert = 0
Global maxVertices = 300000
Global maxFaces = 500000
Global textured = 0
Global normalized = 0
IndicesPerLine = 0


Global Dim x.f(maxVertices) ;vertex coordinates
Global Dim y.f(maxVertices)
Global Dim z.f(maxVertices)
Global Dim nx.f(maxVertices)
Global Dim ny.f(maxVertices)
Global Dim nz.f(maxVertices)
Global Dim u.f(maxVertices)
Global Dim v.f(maxVertices)
Global Dim t.l(100)
Global Dim f.s(50)
Global Dim vt(50)
Global Dim vn(50)

ExamineDesktops()
OpenWindow(3, 0, 0, DesktopWidth(0), DesktopHeight(0), "OBJ  Loader ,  R_Click Show mouse cursor ..... W: Wire/Solid. ...Mouse+Arrow keys: Camera. .. .Space: stop rotation", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)

;Initialize environment
InitEngine3D()
InitSprite()
InitMouse()

OpenWindowedScreen(WindowID(3), 50, 0, DesktopWidth(0), DesktopHeight(0), 0, 0, 0)
ButtonGadget(#but, 0, 10, 50, 60, "Open File")
InitKeyboard()

Add3DArchive(".", #PB_3DArchive_FileSystem)
Add3DArchive(#PB_Compiler_Home + "examples/3d/Data/Textures", #PB_3DArchive_FileSystem)
Add3DArchive(#PB_Compiler_Home + "examples/3d/Data/Scripts",#PB_3DArchive_FileSystem)
Parse3DScripts()

path = OpenFileRequester("Choose file to load", "", "OBJ-Mesh (*.obj)|*.obj", 0, 0)
Add3DArchive(GetPathPart(path), #PB_3DArchive_FileSystem)
If path = "":End:EndIf
;OpenFile(1, GetFilePart(path))
OpenFile(1, path)
;Debug GetPathPart(path)
MakeMesh() ; read OBJ file lines
 
rot = 1
ExamineKeyboard()

Repeat
  If MouseButton(#PB_MouseButton_Right)
    flag = 1: ReleaseMouse(1)
  EndIf
 
  If flag = 0
  If ExamineMouse()
      MouseX = -MouseDeltaX() * 0.1 * 0.5
      MouseY = -MouseDeltaY() * 0.1 * 0.5
  EndIf
  EndIf

  Repeat
    Event = WindowEvent()
 
  Select event
        Case #PB_Event_Gadget
          Select EventGadget()
                     
            Case #but
              FreeEntity(0)
              FreeMesh(0)
              FreeTexture(0)
             
              For i=0 To maxVertices
              x(i)=0:y(i)=0:z(i)=0:nx(i)=0:ny(i)=0:nz(i)=0:u(i)=0:v(i)=0
              Next
              For i=0 To 50:f(i)="":Next
              tri = 0: vert = 0: textured = 0: normalized = 0: vertices = 0: indicesPerLine = 0
              path = OpenFileRequester("Choose file to load", "", "OBJ-Mesh (*.obj)|*.obj", 0, 0)
              Add3DArchive(GetPathPart(path), #PB_3DArchive_FileSystem)
              If path = "":End:EndIf

              ;OpenFile(1, GetFilePart(path))
              OpenFile(1, path)
              SetActiveGadget(-1)
              flag = 0: ReleaseMouse(0)
              Dim MeshData.PB_MeshVertex(0)
              MakeMesh()
                                         
          EndSelect
         
      EndSelect
      Until event = 0

      If ExamineKeyboard()
       
        If KeyboardPushed(#PB_Key_Left)
          KeyX = -CameraSpeed
        ElseIf KeyboardPushed(#PB_Key_Right)
          KeyX = CameraSpeed
        Else
          KeyX = 0
        EndIf
       
        If KeyboardPushed(#PB_Key_Up)
          KeyY = -CameraSpeed
        ElseIf KeyboardPushed(#PB_Key_Down)
          KeyY = CameraSpeed
        Else
          KeyY = 0
        EndIf
       
        If KeyboardReleased(#PB_Key_W)
          wire ! 1
          If wire
            MaterialShadingMode(0, #PB_Material_Wireframe)
          Else
            MaterialShadingMode(0, #PB_Material_Solid)
          EndIf 
        EndIf
       
        If KeyboardReleased(#PB_Key_S)
          SaveMesh(0, "test.mesh")
        EndIf
               
        If KeyboardReleased(#PB_Key_Space)
          rot ! 1
        EndIf
               
         
      EndIf
     
      RotateEntity(0, 0, 0.5*rot, 0, #PB_Relative)
     
      RotateCamera(0, MouseY, MouseX, 0, #PB_Relative)
      MoveCamera  (0, KeyX, 0, KeyY)
           
   RenderWorld()
   FlipBuffers()
   
   
   If KeyboardReleased(#PB_Key_Escape)
     Quit = #True
   EndIf
  Until Quit = #True Or Event = #PB_Event_CloseWindow


Procedure ParseString(st.s)
  Protected.f ax,ay,az,bx,by,bz
  Dim f.s(50)
  Dim vt(50)
  st = RemoveString(st, "f")
  st = Trim(st)
  k = CountString(st, " ") + 1
 
  For i=1 To k+1
    f(i) = StringField(st, i, " ")
  Next
 
  For i=1 To k+1
    t(i) = Val(StringField(f(i), 1, "/"))
    vt(i) = Val(StringField(f(i), 2, "/"))
  Next

  ;vn1 = Val(StringField(f(1), 3, "/"))
  ;vn2 = Val(StringField(f(2), 3, "/"))
  ;vn3 = Val(StringField(f(3), 3, "/"))
 
   ax= x(t(2))-x(t(1))
   ay= y(t(2))-y(t(1))
   az= z(t(2))-z(t(1))
   bx= x(t(3))-x(t(1))
   by= y(t(3))-y(t(1))
   bz= z(t(3))-z(t(1))
   NormX = (ay*bz)-(az*by)
   NormY = (az*bx)-(ax*bz)
   NormZ = (ax*by)-(ay*bx)
  For i=1 To k-1
    ;draw one line
    MeshVertexPosition(x(t(i)),y(t(i)),z(t(i)))
    MeshVertexNormal(NormX,NormY,NormZ)
    MeshVertexTextureCoordinate(u(vt(i)), v(vt(i)))
    MeshVertexPosition(x(t(i+1)),y(t(i+1)),z(t(i+1)))
    MeshVertexNormal(NormX,NormY,NormZ)
    MeshVertexTextureCoordinate(u(vt(i+1)), v(vt(i+1)))
   
  Next
    ;draw last line in the Polygon
    MeshVertexPosition(x(t(k)),y(t(k)),z(t(k)))
    MeshVertexNormal(NormX,NormY,NormZ)
    MeshVertexTextureCoordinate(u(vt(k)), v(vt(k)))
    MeshVertexPosition(x(t(1)),y(t(1)),z(t(1))) ; it close to vertex 1
    MeshVertexNormal(NormX,NormY,NormZ)
   
       
  For n=0 To 100
    t(n)=0
  Next
 
EndProcedure

Procedure MakeMesh()


CreateMesh(0, #PB_Mesh_LineList, #PB_Mesh_Static )

While Not Eof(1)
 
  ln$ = ReadString(1)
  ;ln$ = ReplaceString(ln$, "  ", " ")
  While FindString(ln$, "  ") > 0
   ln$ = ReplaceString(ln$, "  ", " ")
  Wend
  If Left(ln$, 2) = "vt"
    textured = 1: normalized = 1
    vert + 1
    u(vert) = ValF(StringField(ln$, 2, " "))
    v(vert) = ValF(StringField(ln$, 3, " "))
   
  EndIf
  If vert >= maxVertices:Break:EndIf
Wend
vert = 0

FileSeek(1,0)

While Not Eof(1)
 
  ln$ = ReadString(1)
  ;ln$ = ReplaceString(ln$, "  ", " ")
  ;ln$ = ReplaceString(ln$, "  ", " ")
  While FindString(ln$, "  ") > 0
   ln$ = ReplaceString(ln$, "  ", " ")
  Wend
  t+1
  If Left(ln$, 2) = "v "
    vertices = vertices+1
    ;ReDim x(vertices): ReDim y(vertices): ReDim z(vertices)
    x(vertices) = ValF(StringField(ln$, 2, " "))
    y(vertices) = ValF(StringField(ln$, 3, " "))
    z(vertices) = ValF(StringField(ln$, 4, " "))
    ;MeshVertexPosition(x(vertices), y(vertices), z(vertices))
  ElseIf Left(ln$, 2) = "vn"
    normalized = 1
    vert + 1
    ;If vert = maxVert:Break:EndIf
    nx(vert) = ValF(StringField(ln$, 2, " "))
    ny(vert) = ValF(StringField(ln$, 3, " "))
    nz(vert) = ValF(StringField(ln$, 4, " "))
 
  EndIf   
 If vertices >= maxVertices:Break:EndIf   
Wend


FileSeek(1,0)
tri = 0: i =0
Global.f ax,ay,az,bx,by,bz,sq,rcent

While Not Eof(1)
 
  ln$ = ReadString(1)
  ;ln$ = ReplaceString(ln$, "  ", " ")
  ;ln$ = ReplaceString(ln$, "  ", " ")
  While FindString(ln$, "  ") > 0
   ln$ = ReplaceString(ln$, "  ", " ")
  Wend
  If Left(ln$, 1) = "f"
    st.s = ln$
   
   ParseString(st.s)

   tri + 1
   
  EndIf
  If tri >= maxFaces:Break:EndIf   
Wend

CloseFile(1)       
   
    ;NormalizeMesh(0)
    FinishMesh(#True)
    ;NormalizeMesh(0) ; gives error
    GetMeshData(0,0, MeshData(), #PB_Mesh_Vertex, 0, MeshVertexCount(0)-1)
    ChangeMesh()
   
    UpdateMeshBoundingBox(0)

    If textured
      CreateMaterial(0, LoadTexture(0, "ground_diffuse.png"))
      MaterialCullingMode(0, #PB_Material_NoCulling)
      CreateEntity(0, MeshID(0), MaterialID(0))
    Else
      CreateMaterial(0, LoadTexture(0, "White.jpg"))
      MaterialCullingMode(0, #PB_Material_NoCulling)
      CreateEntity(0, MeshID(0), MaterialID(0))
    EndIf
   
    CreateCamera(0, 0, 0, 100, 100)
   
    MeshRad.f = MeshRadius(0)
    ScaleEntity(0, 1.244/MeshRad, 1.24/MeshRad, 1.24/MeshRad)
    MoveCamera(0, 0, 2, 3, #PB_Absolute)
    CameraLookAt(0, 0,0,0)
   
    CreateLight(0, RGB(200,150,100), 10, 2000, 300)
    AmbientColor(RGB(90, 90, 60))
 
 
EndProcedure

Procedure ChangeMesh()
  ; by Comtois 
  Protected.f minx, miny, minz, maxx, maxy, maxz
  Protected.f corx, cory, corz
  minx =  999999
  miny =  999999
  minz =  999999
  maxx = -999999
  maxy = -999999
  maxz = -999999
 
  For i=0 To ArraySize(MeshData())
    If MeshData(i)\x > maxx
      maxx = MeshData(i)\x
    EndIf
    If MeshData(i)\x < minx
      minx = MeshData(i)\x
    EndIf   
    If MeshData(i)\y > maxy
      maxy = MeshData(i)\y
    EndIf
    If MeshData(i)\y < miny
      miny = MeshData(i)\y
    EndIf   
    If MeshData(i)\z > maxz
      maxz = MeshData(i)\z
    EndIf
    If MeshData(i)\z < minz
      minz = MeshData(i)\z
    EndIf       
  Next 
  corx = (-maxx - minx) /2.0
  cory = (-maxy - miny) /2.0
  corz = (-maxz - minz) /2.0

  For i=0 To ArraySize(MeshData())
    MeshData(i)\x + corx
    MeshData(i)\y + cory
    MeshData(i)\z + corz     
  Next 
  SetMeshData(0,0, MeshData(), #PB_Mesh_Vertex, 0, MeshVertexCount(0)-1)
EndProcedure



the second demo use triangles (#PB_Mesh_TriangleList) and will triangulate the possible polygons, and if they have texture coordinates then will apply a default texture.
regarding the submeshes , the second code below will read the lines begins with "g " and consider it a submesh, a showcase only demonstrated if you load spider.obj: texturing the eyes and the belly.
EDITED: to remove the extra spaces from some files
Code:
;DisableDebugger
Global CameraSpeed.f = 0.02

Declare ParseString(st.s)
Declare MakeMesh()
Declare ChangeMesh()

Global Dim MeshData.PB_MeshVertex(0) ; for centering the mesh only

Define.f KeyX, KeyY, MouseX, MouseY
Quit.b = #False
#but = 10 ; button

Global.s path
Define.f x, y, z, nx, ny, nz, u, v
Global vert.l
Global tri.l, i.l, IndicesPerLine.l
Global st.s
Global.f NormX, NormY, NormZ
Global IndicesPerLine
Global vertices = 0
tri = 0
vert = 0
Global maxVertices = 300000
Global maxFaces = 500000
Global textured = 0
Global normalized = 0
Global pp
IndicesPerLine = 0


Global Dim x.f(maxVertices) ;vertex coordinates
Global Dim y.f(maxVertices)
Global Dim z.f(maxVertices)
Global Dim nx.f(maxVertices)
Global Dim ny.f(maxVertices)
Global Dim nz.f(maxVertices)
Global Dim u.f(maxVertices)
Global Dim v.f(maxVertices)
Global Dim t.l(100)
Global Dim f.s(50)
Global Dim vt(50)
Global Dim vn(50)

ExamineDesktops()
OpenWindow(3, 0, 0, DesktopWidth(0), DesktopHeight(0), "OBJ  Loader ,  R_Click Show mouse cursor ..... W: Wire/Solid. ...Mouse+Arrow keys: Camera. .. .Space: stop rotation", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)

;Initialize environment
InitEngine3D()
InitSprite()
InitMouse()

OpenWindowedScreen(WindowID(3), 50, 0, DesktopWidth(0), DesktopHeight(0), 0, 0, 0)
ButtonGadget(#but, 0, 10, 50, 60, "Open File")
InitKeyboard()

Add3DArchive(".", #PB_3DArchive_FileSystem)
Add3DArchive(#PB_Compiler_Home + "examples/3d/Data/Textures", #PB_3DArchive_FileSystem)
Add3DArchive(#PB_Compiler_Home + "examples/3d/Data/Scripts",#PB_3DArchive_FileSystem)
Parse3DScripts()

path = OpenFileRequester("Choose file to load", "", "OBJ-Mesh (*.obj)|*.obj", 0, 0)
Add3DArchive(GetPathPart(path), #PB_3DArchive_FileSystem)
If path = "":End:EndIf
;OpenFile(1, GetFilePart(path))
OpenFile(1, path)

MakeMesh() ; read OBJ file lines
 
rot = 1
ExamineKeyboard()

Repeat
  If MouseButton(#PB_MouseButton_Right)
    flag = 1: ReleaseMouse(1)
  EndIf
 
  If flag = 0
  If ExamineMouse()
      MouseX = -MouseDeltaX() * 0.1 * 0.5
      MouseY = -MouseDeltaY() * 0.1 * 0.5
  EndIf
  EndIf

  Repeat
    Event = WindowEvent()
 
  Select event
        Case #PB_Event_Gadget
          Select EventGadget()
                     
            Case #but
              FreeEntity(0)
              FreeMesh(0)
              FreeTexture(0)
             
              For i=0 To maxVertices
              x(i)=0:y(i)=0:z(i)=0:nx(i)=0:ny(i)=0:nz(i)=0:u(i)=0:v(i)=0
            Next
            For i=0 To 50:f(i)="":Next
              tri = 0: vert = 0: textured = 0: normalized = 0: vertices = 0: indicesPerLine = 0
              path = OpenFileRequester("Choose file to load", "", "OBJ-Mesh (*.obj)|*.obj", 0, 0)
              If path = "":End:EndIf

              ;OpenFile(1, GetFilePart(path))
              OpenFile(1, path)
              SetActiveGadget(-1)
              flag = 0: ReleaseMouse(0) : wire = 0
              Dim MeshData.PB_MeshVertex(0)
              MakeMesh()
                                         
          EndSelect
         
      EndSelect
      Until event = 0

      If ExamineKeyboard()
       
        If KeyboardPushed(#PB_Key_Left)
          KeyX = -CameraSpeed
        ElseIf KeyboardPushed(#PB_Key_Right)
          KeyX = CameraSpeed
        Else
          KeyX = 0
        EndIf
       
        If KeyboardPushed(#PB_Key_Up)
          KeyY = -CameraSpeed
        ElseIf KeyboardPushed(#PB_Key_Down)
          KeyY = CameraSpeed
        Else
          KeyY = 0
        EndIf
       
        If KeyboardReleased(#PB_Key_W)
          wire ! 1
          If wire
            MaterialShadingMode(0, #PB_Material_Wireframe)
          Else
            MaterialShadingMode(0, #PB_Material_Solid)
          EndIf 
        EndIf
       
        If KeyboardReleased(#PB_Key_S)
          SaveMesh(0, "spider3.mesh")
        EndIf
               
        If KeyboardReleased(#PB_Key_Space)
          rot ! 1
        EndIf
               
         
      EndIf
     
      RotateEntity(0, 0, 0.5*rot, 0, #PB_Relative)
     
      RotateCamera(0, MouseY, MouseX, 0, #PB_Relative)
      MoveCamera  (0, KeyX, 0, KeyY)
           
   RenderWorld()
   FlipBuffers()
   
   
   If KeyboardReleased(#PB_Key_Escape)
     Quit = #True
   EndIf
  Until Quit = #True Or Event = #PB_Event_CloseWindow


Procedure ParseString(st.s)
  Protected.f ax,ay,az,bx,by,bz
  st = RemoveString(st, "f")
  st = Trim(st)
  k = CountString(st, " ") + 1
 
  For i=1 To k+1
    f(i) = StringField(st, i, " ")
  Next
 
  For i=1 To k+1
    t(i) = Val(StringField(f(i), 1, "/"))
    vt(i) = Val(StringField(f(i), 2, "/"))
    vn(i) = Val(StringField(f(i), 3, "/"))
  Next
 
  If (textured And Not normalized) Or Not normalized
   i=1
   ;just simple normalizarion
   ax= x(t(2))-x(t(1))
   ay= y(t(2))-y(t(1))
   az= z(t(2))-z(t(1))
   bx= x(t(3))-x(t(1))
   by= y(t(3))-y(t(1))
   bz= z(t(3))-z(t(1))
   NormX = (ay*bz)-(az*by)
   NormY = (az*bx)-(ax*bz)
   NormZ = (ax*by)-(ay*bx)
   ;triangulation of the polygon
   ;the first triangle of the polygon
    MeshVertexPosition(x(t(i)),y(t(i)),z(t(i)))
    MeshVertexNormal(NormX,NormY,NormZ)
    MeshVertexTextureCoordinate(u(vt(i)), v(vt(i)))
       
    MeshVertexPosition(x(t(i+1)),y(t(i+1)),z(t(i+1)))
    MeshVertexNormal(NormX,NormY,NormZ)
    MeshVertexTextureCoordinate(u(vt(i+1)), v(vt(i+1)))
   
    MeshVertexPosition(x(t(i+2)),y(t(i+2)),z(t(i+2)))
    MeshVertexNormal(NormX,NormY,NormZ)
    MeshVertexTextureCoordinate(u(vt(i+2)), v(vt(i+2)))
   
  ;remaining triangles of the the polygon
  i=i+2
  While i < k
   
    MeshVertexPosition(x(t(i)),y(t(i)),z(t(i)))
    MeshVertexNormal(NormX,NormY,NormZ)
    MeshVertexTextureCoordinate(u(vt(i)), v(vt(i)))
   
    MeshVertexPosition(x(t(i+1)),y(t(i+1)),z(t(i+1)))
    MeshVertexNormal(NormX,NormY,NormZ)
    MeshVertexTextureCoordinate(u(vt(i+1)), v(vt(i+1)))
   
    MeshVertexPosition(x(t(1)),y(t(1)),z(t(1)))
    MeshVertexNormal(NormX,NormY,NormZ)
    MeshVertexTextureCoordinate(u(vt(1)), v(vt(1)))
    i+1
   
  Wend
 
ElseIf textured Or normalized

   ;triangulation of the polygon
   ;first triangle
    i=1
    MeshVertexPosition(x(t(i)),y(t(i)),z(t(i)))
    MeshVertexNormal(nx(vn(i)), ny(vn(i)), nz(vn(i)))
    MeshVertexTextureCoordinate(u(vt(i)), v(vt(i)))
       
    MeshVertexPosition(x(t(i+1)),y(t(i+1)),z(t(i+1)))
    MeshVertexNormal(nx(vn(i+1)), ny(vn(i+1)), nz(vn(i+1)))
    MeshVertexTextureCoordinate(u(vt(i+1)), v(vt(i+1)))
   
    MeshVertexPosition(x(t(i+2)),y(t(i+2)),z(t(i+2)))
    MeshVertexNormal(nx(vn(i+2)), ny(vn(i+2)), nz(vn(i+2)))
    MeshVertexTextureCoordinate(u(vt(i+2)), v(vt(i+2)))
   
  ;remaining triangles 
  i=i+2
  While i < k
   
    MeshVertexPosition(x(t(i)),y(t(i)),z(t(i)))
    MeshVertexNormal(nx(vn(i)), ny(vn(i)), nz(vn(i)))
    MeshVertexTextureCoordinate(u(vt(i)), v(vt(i)))
   
    MeshVertexPosition(x(t(i+1)),y(t(i+1)),z(t(i+1)))
    MeshVertexNormal(nx(vn(i+1)), ny(vn(i+1)), nz(vn(i+1)))
    MeshVertexTextureCoordinate(u(vt(i+1)), v(vt(i+1)))
   
    MeshVertexPosition(x(t(1)),y(t(1)),z(t(1)))
    MeshVertexNormal(nx(vn(1)), ny(vn(1)), nz(vn(1)))
    MeshVertexTextureCoordinate(u(vt(1)), v(vt(1)))
    i+1
   
  Wend

EndIf

  For n=0 To 100
    t(n)=0
  Next
 
EndProcedure

Procedure MakeMesh()


CreateMesh(0, #PB_Mesh_TriangleList, #PB_Mesh_Dynamic )

While Not Eof(1)
 
  ln$ = ReadString(1)
  ;ln$ = ReplaceString(ln$, "  ", " ")
  While FindString(ln$, "  ") > 0
    ln$ = ReplaceString(ln$, "  ", " ")
  Wend
  If Left(ln$, 2) = "vt"
    textured = 1
    vert + 1
    submeshFlag=0
    u(vert) = ValF(StringField(ln$, 2, " "))
    v(vert) = ValF(StringField(ln$, 3, " "))
   
  EndIf
  If vert >= maxVertices:Break:EndIf
Wend
vert = 0

FileSeek(1,0)

While Not Eof(1)
 
  ln$ = ReadString(1)
  While FindString(ln$, "  ") > 0
   ln$ = ReplaceString(ln$, "  ", " ")
  Wend
  ;ln$ = ReplaceString(ln$, "  ", " ")
  t+1
  If Left(ln$, 2) = "v "
    vertices = vertices+1
    submeshFlag=0
    ;ReDim x(vertices): ReDim y(vertices): ReDim z(vertices)
    x(vertices) = ValF(StringField(ln$, 2, " "))
    y(vertices) = ValF(StringField(ln$, 3, " "))
    z(vertices) = ValF(StringField(ln$, 4, " "))
   
  ElseIf Left(ln$, 2) = "vn"
    normalized = 1
    vert + 1
    nx(vert) = ValF(StringField(ln$, 2, " "))
    ny(vert) = ValF(StringField(ln$, 3, " "))
    nz(vert) = ValF(StringField(ln$, 4, " "))
       
  EndIf
 
 If vertices >= maxVertices:Break:EndIf   
Wend


FileSeek(1,0)
tri = 0: i =0

While Not Eof(1)
 
  ln$ = ReadString(1)
  While FindString(ln$, "  ") > 0
   ln$ = ReplaceString(ln$, "  ", " ")
  Wend
  ;ln$ = ReplaceString(ln$, "  ", " ")
  If Left(ln$, 2) = "g ":
    AddSubMesh(#PB_Mesh_TriangleList)
  EndIf
 
  If Left(ln$, 1) = "f"
    st.s = ln$
   
   ParseString(st.s)
;Debug tri
   tri + 1
   
  EndIf
  If tri >= maxFaces:Break:EndIf ; to break loading very big meshes like hairball.obj
Wend

CloseFile(1)       
   
FinishMesh(#True)
;NormalizeMesh(0) ; gives error
subMeshes = SubMeshCount(0)

GetMeshData(0,0, MeshData(), #PB_Mesh_Vertex, 0, MeshVertexCount(0)-1)
ChangeMesh()

UpdateMeshBoundingBox(0)
CreateMaterial(1, LoadTexture(1, "RustySteel.jpg"))
MaterialCullingMode(1, #PB_Material_NoCulling)
DisableMaterialLighting(1, 1)

CreateMaterial(0, LoadTexture(0, "ground_diffuse.png"))
   
    If textured
      CreateMaterial(0, LoadTexture(0, "ground_diffuse.png"))
      ;CreateMaterial(0, LoadTexture(0, "SpiderTex.jpg"))
      MaterialCullingMode(0, #PB_Material_NoCulling)
      CreateEntity(0, MeshID(0), MaterialID(0));#PB_Material_None);MaterialID(17)) ;
    Else
      CreateMaterial(0, LoadTexture(0, "White.jpg"))
      SetMaterialColor(0, #PB_Material_SpecularColor, RGB(255,0,0))
      MaterialCullingMode(0, #PB_Material_NoCulling)
      CreateEntity(0, MeshID(0), MaterialID(0))
    EndIf
   
    If subMeshes = 19 ; only for the spider mesh as a showcase for submeshes texturing
      CreateMaterial(2, LoadTexture(2, "Geebee2.bmp"));"Lensflare5.jpg"));"engineflare1.jpg"))
      MaterialCullingMode(2, #PB_Material_NoCulling)
      DisableMaterialLighting(2, 1)
      CreateEntity(0, MeshID(0), MaterialID(0))
      SetEntityMaterial(0, MaterialID(1),0) ; belly
      SetEntityMaterial(0, MaterialID(0),1)
      SetEntityMaterial(0, MaterialID(2),17) ; spider eye
      SetEntityMaterial(0, MaterialID(2),18) ; spider eye
    EndIf
   
   
   
    CreateCamera(0, 0, 0, 100, 100)
   
    MeshRad.f = MeshRadius(0)
    ScaleEntity(0, 1.244/MeshRad, 1.24/MeshRad, 1.24/MeshRad)
    MoveCamera(0, 0, 2, 3, #PB_Absolute)
    CameraLookAt(0, 0,0,0)
   
    CreateLight(0, RGB(200,150,100), 10, 2000, 300)
    AmbientColor(RGB(90, 90, 60))
 
 
  EndProcedure
 
  Procedure ChangeMesh()
  ; by Comtois 
  Protected.f minx, miny, minz, maxx, maxy, maxz
  Protected.f corx, cory, corz
  minx =  999999
  miny =  999999
  minz =  999999
  maxx = -999999
  maxy = -999999
  maxz = -999999
 
  For i=0 To ArraySize(MeshData())
    If MeshData(i)\x > maxx
      maxx = MeshData(i)\x
    EndIf
    If MeshData(i)\x < minx
      minx = MeshData(i)\x
    EndIf   
    If MeshData(i)\y > maxy
      maxy = MeshData(i)\y
    EndIf
    If MeshData(i)\y < miny
      miny = MeshData(i)\y
    EndIf   
    If MeshData(i)\z > maxz
      maxz = MeshData(i)\z
    EndIf
    If MeshData(i)\z < minz
      minz = MeshData(i)\z
    EndIf       
  Next 
  corx = (-maxx - minx) /2.0
  cory = (-maxy - miny) /2.0
  corz = (-maxz - minz) /2.0

  For i=0 To ArraySize(MeshData())
    MeshData(i)\x + corx
    MeshData(i)\y + cory
    MeshData(i)\z + corz     
  Next 
  SetMeshData(0,0, MeshData(), #PB_Mesh_Vertex, 0, MeshVertexCount(0)-1)
EndProcedure



press 'S' to save a test.mesh suitable for PB Ogre

some tools:
1-the best models viewer (for OBJ and others) is the small and free view3dscene from https://castle-engine.sourceforge.io/view3dscene.php
2- to convert OBJ or 3DS or other models to Ogre Mesh use
OgreASSIMPConverte from http://www.purebasic.fr/english/viewtop ... 22#p401729


Last edited by applePi on Thu May 25, 2017 3:27 pm, edited 6 times in total.

Top
 Profile  
Reply with quote  
 Post subject: Re: wavefront OBJ files Loader
PostPosted: Fri May 05, 2017 2:50 pm 
Offline
Addict
Addict
User avatar

Joined: Sat Feb 19, 2005 2:46 pm
Posts: 1676
Location: Pas-de-Calais, France
It works remarkably well with several big objects I have ! Thank you, could be useful. :)

_________________
Prehistoric games - Bobble Puzzle, Purebreaker 3 ~> http://djes.free.fr


Top
 Profile  
Reply with quote  
 Post subject: Re: wavefront OBJ files Loader
PostPosted: Sun May 07, 2017 8:47 pm 
Offline
Addict
Addict
User avatar

Joined: Sun Nov 05, 2006 11:42 pm
Posts: 3867
Location: Lyon - France
Cool works fine, like usually 8)
After several obj in your zip, I have try the head, very nice :D

With "LoadObjMesh_Tri.pb" i have also try the "cornell-box" and "CornellBox-Empty-CO.obj" and i have an error at this line :|
Code:
  ;just simple normalizarion
   ax= x(t(2))-x(t(1))

And also several others "CornellBox-Glossy.obj"

I have W10 X64 PB v5.60(x86)

Thanks again for your perpetual splendid works 8)

_________________
ImageThe happiness is a road...
Not a destination


Top
 Profile  
Reply with quote  
 Post subject: Re: wavefront OBJ files Loader
PostPosted: Mon May 08, 2017 10:46 am 
Offline
Addict
Addict

Joined: Sun Jun 25, 2006 7:28 pm
Posts: 1255
Thank you djes and Kwai chang caine
Thanks for reporting a bug , i have opened the CornellBox-Empty-CO.obj file with notepad and it seems the error is because the indexes have negative values such as f -4 -3 -2 -1
usualy and in most cases it is positive. -1 means the last point, it is a relative indexes. can't insert this idea in my spaghetti steel of coding, it is may be very simple change but i don't get it. will look at this later.
CornellBox-Glossy + CornellBox-Sphere.obj + CornellBox-Water.obj works for me (look the first code marked EDITED, the CornellBox-Water.obj in interesting. the others does not work, if they have negative indices.

here is another obj files examples, i have tested it all (the minicooper.obj takes 5 seconds to load):
http://people.sc.fsu.edu/~jburkardt/data/obj/obj.html
http://wikisend.com/download/242146/obj_files.7z

in fact i suggest PureBasic to support OBJ files, will be great, since it is simpler than other 3D files and it is a text files with OBJ extension. and it does not have animation so it is easier to implement, it is available in all and every thing ie natural and classic


Last edited by applePi on Mon May 08, 2017 11:36 am, edited 2 times in total.

Top
 Profile  
Reply with quote  
 Post subject: Re: wavefront OBJ files Loader
PostPosted: Mon May 08, 2017 11:13 am 
Offline
Addict
Addict
User avatar

Joined: Sat Feb 19, 2005 2:46 pm
Posts: 1676
Location: Pas-de-Calais, France
I totally agree, on my last work I've abandonned pb for 3D, because of the lack of object import possibilities, even if it was the first tool I've tested. Conversion tools are a mess, and with really big objects, most are unstable. As it was on point clouds, a medium sized scan has 20 million points... Anyway, your simple code permits it, proving that PB could do the stuff. I've tested some other tools, and what I need is really something handling a lot of low level stuff.

_________________
Prehistoric games - Bobble Puzzle, Purebreaker 3 ~> http://djes.free.fr


Top
 Profile  
Reply with quote  
 Post subject: Re: wavefront OBJ files Loader
PostPosted: Wed May 10, 2017 8:23 am 
Offline
Addict
Addict

Joined: Sun Jun 25, 2006 7:28 pm
Posts: 1255
in purebasic when we add Submesh (any time) the indices to vertices begins with index zero and up . in some OBJ files it is like this
f -4 -3 -2 -1
with -1 refer to the last created vertex, and -4 refer to the first created vertex in the newest submesh.
to translate something like f -4 -3 -2 -1 to purebasic Ogre we first find the smallest number (the biggest in negative direction) and then adding its absolute value to all negative numbers so then we turn it to usual PB indice going from 0 and up
here is the vertices data and the indices in CornellBox-Empty-CO.obj in the package http://graphics.williams.edu/data/meshe ... ll-box.zip
this is the line of thought to follow when we want to add support to negative indices.
it is useful in designing delicate shapes, but not in big meshes (will be too many submeshes)
Image

Code:
Procedure.l Min (Array a.l(1))
  ;http://rosettacode.org/wiki/Greatest_element_of_a_list#PureBasic
  ;example: Debug Min(a())
   Protected last, i, ret.f
 
   ret = a(0)   
   last = ArraySize(a())
   For i = 1 To last
      If ret > a(i) ; for Max change > to <
         ret = a(i)
      EndIf
   Next
 
   ProcedureReturn ret
 EndProcedure
 

IncludeFile #PB_Compiler_Home + "examples/3d/Screen3DRequester.pb"


If InitEngine3D()
 
  Add3DArchive(#PB_Compiler_Home + "examples/3d/Data/Textures", #PB_3DArchive_FileSystem)
  Add3DArchive(#PB_Compiler_Home + "examples/3d/Data/fonts", #PB_3DArchive_FileSystem)
  Add3DArchive(#PB_Compiler_Home + "examples/3d/Data/Scripts", #PB_3DArchive_FileSystem)
  Parse3DScripts()
 
  InitSprite()
  InitKeyboard()
  InitMouse()
 
  If Screen3DRequester()
   
    ;- Material
    CreateMaterial(0, LoadTexture(0, "White.jpg"))
    DisableMaterialLighting(0, #True)
   
   ;******************************************************************
    Define.f x,y,z
    Dim indx.l(3)
 
   CreateMesh(4, #PB_Mesh_LineStrip, #PB_Mesh_Static)
   Restore vertex
   For i=1 To 6
    AddSubMesh(#PB_Mesh_LineStrip)
    Read.f x: Read.f y: Read.f z
    MeshVertexPosition(x, y, z) ; have indx 0
    Read.f x: Read.f y: Read.f z
    MeshVertexPosition(x, y, z);1
    Read.f x: Read.f y: Read.f z
    MeshVertexPosition(x, y, z) ;2
    Read.f x: Read.f y: Read.f z
    MeshVertexPosition(x, y, z)  ;3
   
    Read.l indx(0): Read.l indx(1): Read.l indx(2): Read.l indx(3)
    min = Min(indx())
    indx(0)-min: indx(1)-min: indx(2)-min: indx(3)-min
    MeshIndex(indx(0)): MeshIndex(indx(1)):MeshIndex(indx(2)):MeshIndex(indx(3)):MeshIndex(indx(0))
   
   Next
 
    FinishMesh(#False)
   
    SetMeshMaterial(4, MaterialID(0))
    Box = CreateNode(#PB_Any, 0, 0, 0)
    AttachNodeObject(Box, MeshID(4))
    MoveNode(Box, 0,0,0)
   
    ;-Camera
    CreateCamera(0, 0, 0, 100, 100)
    MoveCamera(0, 0, 3, 4, #PB_Absolute)
    CameraFOV(0, 60)
    CameraLookAt(0, 0,  0,  0)
    CameraBackColor(0, RGB(0, 0, 40))
   
    ;-Light
    CreateLight(0, RGB(255,255,255), -10, 60, 10)
    AmbientColor(RGB(90, 90, 90))
   
    Repeat
      Screen3DEvents()
     
      ExamineKeyboard()
     
      RotateNode(Box, 0, -1, 0, #PB_Relative)
      RenderWorld()
     
      FlipBuffers()
    Until KeyboardPushed(#PB_Key_Escape) Or Quit = 1
  EndIf
 
Else
  MessageRequester("Error", "The 3D Engine can't be initialized", 0)
EndIf

End

DataSection
vertex: 
Data.f  -1.01,  0.00,   0.99
Data.f  1.00,  0.00,   0.99
Data.f  1.00,  0.00,  -1.04
Data.f  -0.99,  0.00,  -1.04
Data.l -4, -3, -2, -1 ; relative indexes

Data.f  -1.02,  1.99,   0.99 
Data.f  -1.02,  1.99,  -1.04
Data.f   1.00,  1.99,  -1.04
Data.f   1.00,  1.99,   0.99
Data.l -4, -3, -2, -1

Data.f  -0.99,  0.00,  -1.04
Data.f   1.00,  0.00,  -1.04
Data.f   1.00,  1.99,  -1.04
Data.f  -1.02,  1.99,  -1.04
Data.l -4, -3, -2, -1

Data.f   1.00,  0.00,  -1.04   
Data.f   1.00,  0.00,   0.99
Data.f   1.00,  1.99,   0.99
Data.f   1.00,  1.99,  -1.04
Data.l -4, -3, -2, -1

Data.f  -1.01,  0.00,   0.99
Data.f  -0.99,  0.00,  -1.04
Data.f  -1.02,  1.99,  -1.04
Data.f  -1.02,  1.99,   0.99
Data.l -4, -3, -2, -1

Data.f   -0.24,  1.98,   0.16
Data.f   -0.24,  1.98,  -0.22
Data.f    0.23,  1.98,  -0.22
Data.f    0.23,  1.98,   0.16
Data.l -4, -3, -2, -1

EndDataSection


Top
 Profile  
Reply with quote  
 Post subject: Re: wavefront OBJ files Loader
PostPosted: Fri Jun 09, 2017 10:41 pm 
Offline
User
User

Joined: Mon Jan 16, 2006 1:11 am
Posts: 75
This is a very nice OBJ viewer, I like it.

Any chance of adding support to STL format?

Thank you.


Top
 Profile  
Reply with quote  
 Post subject: Re: wavefront OBJ files Loader
PostPosted: Sat Jun 10, 2017 11:12 am 
Offline
Addict
Addict

Joined: Sun Jun 25, 2006 7:28 pm
Posts: 1255
Thank you Pureabc
i have made the Obj Viewer project for the only purpose to view the hairball.obj in http://graphics.williams.edu/data/meshes.xml which have size 236 MBytes and Vertices: 1,441,098 Triangles: 2,880,000 since the available viewers trying to load all the mesh and since it is very big mesh it crashed. but my OBJ viewer loads only part of the very big mesh so it does not crash my computer. the OBJ files is relatively simple to parse.
while stl have more complex structure and it is a text like files and also have a binary mode, it is too much difficult task for me now and can't do it.
thanks for your interest
regards


Top
 Profile  
Reply with quote  
 Post subject: Re: wavefront OBJ files Loader
PostPosted: Sun Jul 16, 2017 11:14 am 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Sat Feb 19, 2011 10:06 am
Posts: 681
Location: Denmark
Normally I do all my conversions to Ogre3D using third party software.
It's a nice piece of code, though.
Thank you.

_________________
“Tell me and I forget. Teach me and I remember. Involve me and I learn.”
— Benjamin Franklin
Current configurations: Windows 7/10, Intel 6800K, Gtx 970, 32 gb ram.


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 9 posts ] 

All times are UTC + 1 hour


Who is online

Users browsing this forum: No registered users and 7 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
Jump to:  

 


Powered by phpBB © 2008 phpBB Group
subSilver+ theme by Canver Software, sponsor Sanal Modifiye