Advertisement
C0BRA

Meh OBJ parser

May 18th, 2012
80
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.93 KB | None | 0 0
  1. struct ObjLexNode
  2. {
  3.     enum NodeType { None, Vertex, Normal, TextureUV, Face, Group, ObjectName } Type;
  4.     union UData
  5.     {
  6.         struct Face_lex
  7.         {
  8.             bool Quad;
  9.             struct Face_part_lex
  10.             {
  11.                 unsigned int VertID;
  12.                 unsigned int TextureCordsID;
  13.                 unsigned int NormID;
  14.             } Part1, Part2, Part3, Part4;
  15.         } Face;
  16.         struct Vertex_lex
  17.         {
  18.             double X, Y, Z;
  19.         } Vertex;
  20.         struct Normal_lex
  21.         {
  22.             double X, Y, Z;
  23.         } Normal;
  24.         struct TextureCord_lex
  25.         {
  26.             double U, V, W;
  27.         } TextureCord;
  28.     } Data;
  29. };
  30.  
  31. void LexObj(const char* pContents, std::list<ObjLexNode*>& out)
  32. {
  33.     unsigned int len = strlen(pContents);
  34.     unsigned int i;
  35.  
  36.     function<void(void)> ReadToNewLine = [&]()
  37.     {
  38.         while(i < len)
  39.         {
  40.             char x = pContents[i];
  41.             if(x == '\n')
  42.                 return;
  43.             i++;
  44.         }
  45.     };
  46.  
  47.     function<void(void)> ReadToNoneSpace = [&]()
  48.     {
  49.         while(i < len)
  50.         {
  51.             char x = pContents[i];
  52.             if(x != ' ' && x != '\t')
  53.                 return;
  54.             i++;
  55.         }
  56.     };
  57.  
  58.     function<bool(const char*)> Peak = [&](const char* pStr) -> bool
  59.     {
  60.         size_t len2 = strlen(pStr);
  61.         for(size_t n = 0; n < len2; n++)
  62.             if(n + i >= len || pStr[n] != pContents[i+n])
  63.                 return false;
  64.         return true;
  65.     };
  66.  
  67.     function<bool(void)> PeakIsNumber = [&]() -> bool
  68.     {
  69.         char pc = pContents[i];
  70.         return pc == '-' || (pc >= 48 && pc <= 57);
  71.     };
  72.  
  73.     function<bool(double&)> ReadDouble = [&](double& out) -> bool
  74.     {
  75.         stringstream ss;
  76.         bool wrotesome = false;
  77.  
  78.         while(i < len)
  79.         {
  80.             char x = pContents[i];
  81.  
  82.             if( (x >= 48 && x <= 57) || x == '.' || x == '-' )
  83.             {
  84.                 ss << x;
  85.                 wrotesome = true;
  86.             }else break;
  87.  
  88.             i++;
  89.         }
  90.  
  91.         out = 0.0;
  92.         if(wrotesome)
  93.             ss >> out;
  94.        
  95.         return wrotesome;
  96.     };
  97.  
  98.     function<bool(int&)> ReadInt = [&](int& out) -> bool
  99.     {
  100.         stringstream ss;
  101.         bool wrotesome = false;
  102.  
  103.         while(i < len)
  104.         {
  105.             char x = pContents[i];
  106.  
  107.             if( x >= 48 && x <= 57 )
  108.             {
  109.                 ss << x;
  110.                 wrotesome = true;
  111.             }else break;
  112.  
  113.             i++;
  114.         }
  115.  
  116.         if(wrotesome)
  117.             ss >> out;
  118.        
  119.         return wrotesome;
  120.     };
  121.  
  122.     function<bool(void)> HandelVert = [&]() -> bool
  123.     {
  124.         double x,y,z;
  125.         i++;
  126.         ReadToNoneSpace();
  127.         if(!ReadDouble(x))
  128.             return false;
  129.         ReadToNoneSpace();
  130.         if(!ReadDouble(y))
  131.             return false;
  132.         ReadToNoneSpace();
  133.         if(!ReadDouble(z))
  134.             return false;
  135.  
  136.         ObjLexNode* node = new ObjLexNode;
  137.         node->Type = node->Vertex;
  138.         node->Data.Vertex.X = x;
  139.         node->Data.Vertex.Y = y;
  140.         node->Data.Vertex.Z = z;
  141.         out.push_back(node);
  142.     };
  143.  
  144.     function<bool(void)> HandelNorm = [&]() -> bool
  145.     {
  146.         double x,y,z;
  147.         i++;
  148.         ReadToNoneSpace();
  149.         if(!ReadDouble(x))
  150.             return false;
  151.         ReadToNoneSpace();
  152.         if(!ReadDouble(y))
  153.             return false;
  154.         ReadToNoneSpace();
  155.         if(!ReadDouble(z))
  156.             return false;
  157.  
  158.         ObjLexNode* node = new ObjLexNode;
  159.         node->Type = node->Normal;
  160.         node->Data.Normal.X = x;
  161.         node->Data.Normal.Y = y;
  162.         node->Data.Normal.Z = z;
  163.         out.push_back(node);
  164.     };
  165.  
  166.     function<bool(void)> HandelTextCord = [&]() -> bool
  167.     {
  168.         double u,v,w;
  169.         i++;
  170.         ReadToNoneSpace();
  171.         if(!ReadDouble(u))
  172.             return false;
  173.         ReadToNoneSpace();
  174.         ReadDouble(v);
  175.         ReadToNoneSpace();
  176.         ReadDouble(w);
  177.  
  178.         ObjLexNode* node = new ObjLexNode;
  179.         node->Type = node->TextureUV;
  180.         node->Data.TextureCord.U = u;
  181.         node->Data.TextureCord.V = v;
  182.         node->Data.TextureCord.W = w;
  183.         out.push_back(node);
  184.     };
  185.  
  186.     function<bool(void)> HandelFace = [&]() -> bool
  187.     {
  188.         i++;
  189.         int v1_lvl = 1, v2_lvl = 1, v3_lvl = 1, v4_lvl = 1;
  190.         int v1 = 0, v1tc = 0, v1n = 0, // Vertex 1, Vert1 text cord, vert 1 normal
  191.             v2 = 0, v2tc = 0, v2n = 0,
  192.             v3 = 0, v3tc = 0, v3n = 0,
  193.             v4 = 0, v4tc = 0, v4n = 0;
  194.         ReadToNoneSpace();
  195.  
  196.         // Vert 1
  197.         if(!ReadInt(v1))
  198.             return false;
  199.         if(Peak("/"))
  200.         {
  201.             v1_lvl++;
  202.             if(!ReadInt(v1tc)) return false;
  203.             if(Peak("/"))
  204.             {
  205.                 if(!ReadInt(v1n)) return false;
  206.                 v1_lvl++;
  207.             }
  208.         }
  209.         ReadToNoneSpace();
  210.  
  211.         //Vert 2
  212.         if(!ReadInt(v2))
  213.             return false;
  214.         if(Peak("/"))
  215.         {
  216.             v2_lvl++;
  217.             if(!ReadInt(v2tc)) return false;
  218.             if(Peak("/"))
  219.             {
  220.                 if(!ReadInt(v2n)) return false;
  221.                 v2_lvl++;
  222.             }
  223.         }
  224.         ReadToNoneSpace();
  225.  
  226.         //Vert 3
  227.         if(!ReadInt(v3))
  228.             return false;
  229.         if(Peak("/"))
  230.         {
  231.             v3_lvl++;
  232.             if(!ReadInt(v3tc)) return false;
  233.             if(Peak("/"))
  234.             {
  235.                 ReadInt(v3n);
  236.                 v3_lvl++;
  237.             }
  238.         }
  239.         ReadToNoneSpace();
  240.        
  241.         bool isquad = false;
  242.  
  243.         // Vert 4?
  244.         if(PeakIsNumber()) // Is a number present
  245.         {
  246.             isquad = true;
  247.  
  248.             // Read vert4
  249.             if(!ReadInt(v4))
  250.                 return false;
  251.             if(Peak("/"))
  252.             {
  253.                 v4_lvl++;
  254.                 if(!ReadInt(v4tc)) return false;
  255.                 if(Peak("/"))
  256.                 {
  257.                     ReadInt(v4n);
  258.                     v4_lvl++;
  259.                 }
  260.             }
  261.             ReadToNoneSpace();
  262.         }
  263.  
  264.         ObjLexNode* node = new ObjLexNode;
  265.         node->Data.Face.Quad = isquad;
  266.  
  267.         node->Type = node->Face;
  268.         node->Data.Face.Part1.VertID = v1;
  269.         node->Data.Face.Part1.TextureCordsID = v1tc;
  270.         node->Data.Face.Part1.NormID = v1n;
  271.  
  272.         node->Data.Face.Part2.VertID = v2;
  273.         node->Data.Face.Part2.TextureCordsID = v2tc;
  274.         node->Data.Face.Part2.NormID = v2n;
  275.  
  276.         node->Data.Face.Part3.VertID = v3;
  277.         node->Data.Face.Part3.TextureCordsID = v3tc;
  278.         node->Data.Face.Part3.NormID = v3n;
  279.  
  280.         node->Data.Face.Part4.VertID = v4;
  281.         node->Data.Face.Part4.TextureCordsID = v4tc;
  282.         node->Data.Face.Part4.NormID = v4n;
  283.  
  284.         out.push_back(node);
  285.  
  286.         return true;
  287.     };
  288.  
  289.     for(i = 0; i < len; i++)
  290.     {
  291.         char x = pContents[i];
  292.  
  293.         if(x == '#')
  294.             ReadToNewLine();
  295.  
  296.         ReadToNoneSpace();
  297.  
  298.         if(Peak("v "))
  299.             HandelVert();
  300.         else if(Peak("f "))
  301.             HandelFace();
  302.         else if(Peak("vn "))
  303.             HandelNorm();
  304.         else if(Peak("vt "))
  305.             HandelTextCord();
  306.     }
  307. }
  308.  
  309. int main()
  310. {
  311.     CFileSystem fs;
  312.  
  313.     ifstream ifs(fs.GetModel("teapot.obj"));
  314.  
  315.     char* inf;
  316.     ifs.seekg(0, ios::end);
  317.     size_t length = ifs.tellg();
  318.     ifs.seekg(0, ios::beg);
  319.  
  320.     inf = new char[length];
  321.     ifs.read(inf, length);
  322.  
  323.     list<ObjLexNode*> lexed;
  324.  
  325.     LexObj(inf, lexed);
  326.  
  327.     cout << "Found nodes:" << lexed.size() << '\n';
  328.  
  329.     delete [] inf;
  330.     // delete node shit too
  331.     return 0;
  332. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement