Mesh I/O Modul

Hier könnt Ihr gute, von Euch geschriebene Codes posten. Sie müssen auf jeden Fall funktionieren und sollten möglichst effizient, elegant und beispielhaft oder einfach nur cool sein.
Lambda
Beiträge: 526
Registriert: 16.06.2011 14:38

Mesh I/O Modul

Beitrag von Lambda »

Ursprünglich um das auslesen von korrekten Polygonen wie durch GetMeshData() zu ermöglichen. Nach längerer Suche wurde ich allerdings fündig. /:->

Mesh I/O (oder einfach Meshio) soll als Vorlage zum importieren von Modell-Formaten dienen. Hinzugefügt habe ich XML Import, falls Interesse besteht führe ich das noch fort. Solange Bones etc. nicht unterstützt sind, ist ein direkter Import animierter Meshes nicht möglich, aber als zentraler Punkt zur Umkonvertierung hilfreich. Mit dem Ogre Converter könnte auch einfach fix eine XML Version durchgejagt werden.



Meshio.pbi

Code: Alles auswählen

EnableExplicit


;- Formats
XIncludeFile "XML.pbi"


DeclareModule Meshio
Structure FACE
  *Vertex.PB_MeshVertex[3]
EndStructure
Structure VERTEXBUFFER
  Map Attribute.s(8)
  List Vertex.PB_MeshVertex()
EndStructure
Structure SUBMESH
  Count.i
  List Face.FACE()
  List VertexBuffer.VERTEXBUFFER()
  Map *Vertex.PB_MeshVertex()
  
  Map Attribute.s(8)
EndStructure
Structure MESHIO
  
  Map *Submesh.SUBMESH()
  List Mesh.SUBMESH()
EndStructure

Declare I(*h.MESHIO, File.s, ShowError.b = #False)
Declare O(*h.MESHIO, File.s, ShowError.b = #False)
EndDeclareModule

  
Module Meshio
  Procedure I(*h.MESHIO, File.s, ShowError.b = #False)
      
      With *h
        Select LCase(GetExtensionPart(File))
          Case "xml"
            MeshXML::I(*h, File, ShowError)
        EndSelect
      EndWith
      
  EndProcedure
  Procedure O(*h.MESHIO, File.s, ShowError.b = #False)
    
    With *h
      Select LCase(GetExtensionPart(File))
        Case "xml"
      EndSelect
    EndWith
    
  EndProcedure
EndModule

UseModule Meshio


CompilerIf #PB_Compiler_IsMainFile
  
  Define MyMesh.MESHIO
  Define File.s = OpenFileRequester("Mesh", "", "Mesh (*.xml)|*.xml|All files (*.*)|*.*", 0)
  
  If File
    Meshio::I(MyMesh, File, #True)
    
    
    ForEach MyMesh\Submesh()
      Debug MyMesh\Submesh()\Count
      Debug MapKey(MyMesh\Submesh())
      
      ; Access triangle-list
      ForEach MyMesh\Submesh()\Face()
        Debug StrF(MyMesh\Submesh()\Face()\Vertex[0]\x, 2)+", "+StrF(MyMesh\Submesh()\Face()\Vertex[1]\x, 2)+", "+StrF(MyMesh\Submesh()\Face()\Vertex[2]\x, 2)
      Next
      
    Next
    
  EndIf
CompilerEndIF

XML.pbi

Code: Alles auswählen

EnableExplicit

DeclareModule MeshXML
Structure FACE
  *Vertex.PB_MeshVertex[3]
EndStructure
Structure VERTEXBUFFER
  Map Attribute.s(8)
  List Vertex.PB_MeshVertex()
EndStructure
Structure SUBMESH
  Count.i
  List Face.FACE()
  List VertexBuffer.VERTEXBUFFER()
  Map *Vertex.PB_MeshVertex()
  
  Map Attribute.s(8)
EndStructure
Structure MESHIO
  
  Map *Submesh.SUBMESH()
  List Mesh.SUBMESH()
EndStructure

  Declare VertexBuffer(*h.MESHIO, *Submesh.SUBMESH, *Node)
  Declare Face(*h.MESHIO, *Submesh.SUBMESH, *Node)
  Declare Submesh(*h.MESHIO, *Node)
  Declare SubmeshIndex(*h.MESHIO, *Node)
  Declare Examine(*h.MESHIO, *Node)
  Declare I(*h.MESHIO, File.s, ShowError.b)
EndDeclareModule

Module MeshXML
Procedure VertexBuffer(*h.MESHIO, *Submesh.SUBMESH, *Node)
  Protected *Child, *VertexBuffer, *Current.PB_MeshVertex, Index
  
  With *Submesh
    *VertexBuffer = ChildXMLNode(*Node)
    
    If *VertexBuffer
      While *VertexBuffer <> 0
        AddElement(\VertexBuffer())
        
        
        ; VertexBuffer-Attributes
        If ExamineXMLAttributes(*VertexBuffer)
          While NextXMLAttribute(*VertexBuffer)
            \VertexBuffer()\Attribute(XMLAttributeName(*VertexBuffer)) = XMLAttributeValue(*VertexBuffer)
          Wend
        EndIf
        
        
        ;[ Vertices
        
        Index = 0
        *Vertex = ChildXMLNode(*VertexBuffer)
        While *Vertex <> 0
          Select GetXMLNodeName(*Vertex)
            Case "vertex"
              
              ; Vertex-Attribute Nodes
              *VertexAttribute = ChildXMLNode(*Vertex)
              
              If *VertexAttribute ;[
                  ; Buffer Vertex
                  AddElement(\VertexBuffer()\Vertex())
                  *Current = @\VertexBuffer()\Vertex()
                  
                  ; Map Vertex
                  \Vertex(Str(Index)) = *Current
                  
                  While *VertexAttribute <> 0
                    Select GetXMLNodeName(*VertexAttribute)
                      Case "position"
                        ;[/ Position
                        If ExamineXMLAttributes(*VertexAttribute)
                          While NextXMLAttribute(*VertexAttribute)
                            Select XMLAttributeName(*VertexAttribute) 
                              Case "x"
                                *Current\x = ValF(XMLAttributeValue(*VertexAttribute))
                              Case "y"
                                *Current\y = ValF(XMLAttributeValue(*VertexAttribute))
                              Case "z"
                                *Current\z = ValF(XMLAttributeValue(*VertexAttribute))
                            EndSelect
                          Wend
                        EndIf
                        ;]/
                      Case "normal"
                        ;[/ Normal
                        If ExamineXMLAttributes(*VertexAttribute)
                          While NextXMLAttribute(*VertexAttribute)
                            Select XMLAttributeName(*VertexAttribute) 
                              Case "x"
                                *Current\NormalX = ValF(XMLAttributeValue(*VertexAttribute))
                              Case "y"
                                *Current\NormalY = ValF(XMLAttributeValue(*VertexAttribute))
                              Case "z"
                                *Current\NormalZ = ValF(XMLAttributeValue(*VertexAttribute))
                            EndSelect
                          Wend
                        EndIf
                        ;]/
                      Case "texcoord"
                        ;[/ UV
                        If ExamineXMLAttributes(*VertexAttribute)
                          While NextXMLAttribute(*VertexAttribute)
                            Select XMLAttributeName(*VertexAttribute) 
                              Case "u"
                                *Current\u = ValF(XMLAttributeValue(*VertexAttribute))
                              Case "v"
                                *Current\v = ValF(XMLAttributeValue(*VertexAttribute))
                            EndSelect
                          Wend
                        EndIf
                        ;]/
                    EndSelect
                    
                    *VertexAttribute = NextXMLNode(*VertexAttribute)
                  Wend
                  ;]
                EndIf
                
            EndSelect
            
            Index + 1
            *Vertex = NextXMLNode(*Vertex)
          Wend
          ;]
          
          
          *VertexBuffer = NextXMLNode(*VertexBuffer)
        Wend
      EndIf
      
    EndWith
EndProcedure
Procedure Face(*h.MESHIO, *Submesh.SUBMESH, *Node)
  With *Submesh
    
    If ExamineXMLAttributes(*Node)
      While NextXMLAttribute(*Node)
        Select XMLAttributeName(*Node)
          Case "count"
            \Count = Val(XMLAttributeValue(*Node))
        EndSelect
      Wend
    Else
      ProcedureReturn #False
    EndIf
    
    
    *Face = ChildXMLNode(*Node)
    If *Face
      While *Face <> 0
        AddElement(\Face())
        
        If ExamineXMLAttributes(*Face)
          While NextXMLAttribute(*Face)
            Select XMLAttributeName(*Face)
              Case "v1"
                \Face()\Vertex[0] = \Vertex(XMLAttributeValue(*Face))
              Case "v2"
                \Face()\Vertex[1] = \Vertex(XMLAttributeValue(*Face))
              Case "v3"
                \Face()\Vertex[2] = \Vertex(XMLAttributeValue(*Face))
            EndSelect
          Wend
        EndIf
        
        *Face = NextXMLNode(*Face)
      Wend
    EndIf
    
    ProcedureReturn #True
  EndWith
EndProcedure
Procedure Submesh(*h.MESHIO, *Node)
  Protected *Child, *Submesh, NewMap *Node()
  
  With *h
    *Submesh = ChildXMLNode(*Node)
    
    If *Submesh
      While *Submesh <> 0
        AddElement(\Mesh())
        
        
        ; Submesh-Attributes
        If ExamineXMLAttributes(*Submesh)
          While NextXMLAttribute(*Submesh)
            \Mesh()\Attribute(XMLAttributeName(*Submesh)) = XMLAttributeValue(*Submesh)
          Wend
        EndIf
        
        
        *Child = ChildXMLNode(*Submesh)
        While *Child <> 0
          Select GetXMLNodeName(*Child)
            Case "faces"
              *Node("faces") = *Child
            Case "geometry"
              *Node("geometry") = *Child
          EndSelect
          *Child = NextXMLNode(*Child)
        Wend
        
        VertexBuffer(*h, @\Mesh(), *Node("geometry"))
        Face(*h, @\Mesh(), *Node("faces"))
        
        
        
        *Submesh = NextXMLNode(*Submesh)
      Wend
    EndIf
    
  EndWith
EndProcedure
Procedure SubmeshIndex(*h.MESHIO, *Node)
  Protected *Submesh, Name.s, Index
  
  With *h
    *Submesh = ChildXMLNode(*Node)
    
    If *Submesh
      While *Submesh <> 0
        
        
        ; Submesh-Association
        If ExamineXMLAttributes(*Submesh)
          While NextXMLAttribute(*Submesh)
            Select XMLAttributeName(*Submesh)
              Case "name"
                Name = XMLAttributeValue(*Submesh)
              Case "index"
                Index = Val(XMLAttributeValue(*Submesh))
            EndSelect
          Wend
        EndIf
        
        ForEach \Mesh()
          If ListIndex(\Mesh()) = Index
            \Submesh(Name) = @\Mesh()
            Break
          EndIf
        Next
        
        
        *Submesh = NextXMLNode(*Submesh)
      Wend
    EndIf
    
  EndWith
EndProcedure

Procedure Examine(*h.MESHIO, *Node)
  Protected *Child, *SubmeshIndex
  
  With *h
    If XMLNodeType(*Node) = #PB_XML_Normal
      While *Node <> 0
        
        Select GetXMLNodeName(*Node)
          Case "submeshes"
            Submesh(*h, *Node)
            
          Case "submeshnames"
            *SubmeshIndex = *Node
            
          Default
            *Child = ChildXMLNode(*Node)
            
            If *Child
              Examine(*h, *Child)
            EndIf
        EndSelect
        
        
        *Node = NextXMLNode(*Node)
      Wend
      
      
      If *SubmeshIndex
        SubmeshIndex(*h, *SubmeshIndex)
      EndIf
    EndIf
  EndWith
  
EndProcedure
Procedure I(*h.MESHIO, File.s, ShowError.b)
  Protected XML, Output.s, *Root
  
  With *h
    
    XML = LoadXML(-1, File)
    
    
    If XMLStatus(XML) <> #PB_XML_Success
      If ShowError
        Output = "Error in the XML file:" + Chr(13)
        Output + "Message: " + XMLError(XML) + Chr(13)
        Output + "Line: " + Str(XMLErrorLine(XML)) + "   Character: " + Str(XMLErrorPosition(XML))
        MessageRequester("Error", Output)
      EndIf
      
      ProcedureReturn #False
    EndIf
    
    *Root = MainXMLNode(XML)      
    If *Root
      Examine(*h, *Root)
    EndIf
    
  EndWith
EndProcedure
EndModule