Advertisement
MechWipf

Untitled

Mar 27th, 2017
68
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 7.67 KB | None | 0 0
  1. local ipairs        = ipairs
  2. local pairs         = pairs
  3. local tonumber      = tonumber
  4.  
  5. local math_sqrt     = math.sqrt
  6. local string_gmatch = string.gmatch
  7. local string_gsub   = string.gsub
  8. local string_match  = string.match
  9. local string_sub    = string.sub
  10. local string_Split  = string.Split
  11. local string_Trim   = string.Trim
  12. local table_concat  = table.concat
  13. local table_insert  = table.insert
  14.  
  15. local Vector        = Vector
  16.  
  17. local function ParseObj(data, generateNormals)
  18.     local coroutine_yield = coroutine.running () and coroutine.yield or function () end
  19.  
  20.     local positions  = {}
  21.     local texCoordsU = {}
  22.     local texCoordsV = {}
  23.     local normals    = {}
  24.  
  25.     local triangleList = {}
  26.  
  27.     local lines = {}
  28.     local faceLines = {}
  29.  
  30.     local i = 1
  31.     local inContinuation    = false
  32.     local continuationLines = nil
  33.     for line in string_gmatch (data, "(.-)\n") do
  34.         local continuation = string_match (line, "\\\r?$")
  35.         if continuation then
  36.             line = string_sub (line, 1, -#continuation - 1)
  37.             if inContinuation then
  38.                 continuationLines[#continuationLines + 1] = line
  39.             else
  40.                 inContinuation    = true
  41.                 continuationLines = { line }
  42.             end
  43.         else
  44.             if inContinuation then
  45.                 continuationLines[#continuationLines + 1] = line
  46.                 lines[#lines + 1] = table_concat (continuationLines)
  47.                 inContinuation    = false
  48.                 continuationLines = nil
  49.             else
  50.                 lines[#lines + 1] = line
  51.             end
  52.         end
  53.  
  54.         coroutine_yield(false, "Preprocessing lines", i)
  55.         i = i + 1
  56.     end
  57.  
  58.     if inContinuation then
  59.         continuationLines[#continuationLines + 1] = line
  60.         lines[#lines + 1] = table.concat (continuationLines)
  61.         inContinuation    = false
  62.         continuationLines = nil
  63.     end
  64.  
  65.     local lineCount = #lines
  66.     local inverseLineCount = 1 / lineCount
  67.     local i = 1
  68.     while i <= lineCount do
  69.         local processedLine = false
  70.  
  71.         -- Positions: v %f %f %f [%f]
  72.         while i <= lineCount do
  73.             local line = lines[i]
  74.             local x, y, z = string_match(line, "^%s*v%s+(%-?%d*%.?%d*e?[+-]?%d*%.?%d*)%s+(%-?%d*%.?%d*e?[+-]?%d*%.?%d*)%s+(%-?%d*%.?%d*e?[+-]?%d*%.?%d*)")
  75.             if not x then break end
  76.  
  77.             processedLine = true
  78.             x, y, z = tonumber(x) or 0, tonumber(y) or 0, tonumber(z) or 0
  79.             positions[#positions + 1] = Vector(x, y, z)
  80.  
  81.             coroutine_yield(false, "Processing vertices", i * inverseLineCount)
  82.             i = i + 1
  83.         end
  84.  
  85.         -- Texture coordinates: vt %f %f
  86.         while i <= lineCount do
  87.             local line = lines[i]
  88.             local u, v = string_match(line, "^%s*vt%s+(%-?%d*%.?%d*e?[+-]?%d*%.?%d*)%s+(%-?%d*%.?%d*e?[+-]?%d*%.?%d*)")
  89.             if not u then break end
  90.  
  91.             processedLine = true
  92.             u, v = tonumber(u) or 0, tonumber(v) or 0
  93.  
  94.             local texCoordIndex = #texCoordsU + 1
  95.             texCoordsU[texCoordIndex] =      u  % 1
  96.             texCoordsV[texCoordIndex] = (1 - v) % 1
  97.  
  98.             coroutine_yield(false, "Processing vertices", i * inverseLineCount)
  99.             i = i + 1
  100.         end
  101.  
  102.         -- Normals: vn %f %f %f
  103.         while i <= lineCount do
  104.             local line = lines[i]
  105.             local nx, ny, nz = string_match(line, "^%s*vn%s+(%-?%d*%.?%d*e?[+-]?%d*%.?%d*)%s+(%-?%d*%.?%d*e?[+-]?%d*%.?%d*)%s+(%-?%d*%.?%d*e?[+-]?%d*%.?%d*)")
  106.             if not nx then break end
  107.  
  108.             processedLine = true
  109.  
  110.             if not generateNormals then
  111.                 nx, ny, nz = tonumber(nx) or 0, tonumber(ny) or 0, tonumber(nz) or 0
  112.  
  113.                 local inverseLength = 1 / math_sqrt(nx * nx + ny * ny + nz * nz)
  114.                 nx, ny, nz = nx * inverseLength, ny * inverseLength, nz * inverseLength
  115.  
  116.                 local normal = Vector(nx, ny, nz)
  117.                 normals[#normals + 1] = normal
  118.             end
  119.  
  120.             coroutine_yield(false, "Processing vertices", i * inverseLineCount)
  121.             i = i + 1
  122.         end
  123.  
  124.         -- Faces: f %f %f %f+
  125.         while i <= lineCount do
  126.             local line = lines[i]
  127.             if not string_match(line, "^%s*f%s+") then break end
  128.  
  129.             processedLine = true
  130.             line = string_match (line, "^%s*(.-)[#%s]*$")
  131.  
  132.             -- Explode line
  133.             local parts = {}
  134.             for part in string_gmatch(line, "[^%s]+") do
  135.                 parts[#parts + 1] = part
  136.             end
  137.             faceLines[#faceLines + 1] = parts
  138.  
  139.             coroutine_yield(false, "Processing vertices", i * inverseLineCount)
  140.             i = i + 1
  141.         end
  142.  
  143.         -- Something else
  144.         if not processedLine then
  145.             i = i + 1
  146.         end
  147.     end
  148.  
  149.     local faceLineCount = #faceLines
  150.     local inverseFaceLineCount = 1 / faceLineCount
  151.     for i = 1, #faceLines do
  152.         local parts = faceLines [i]
  153.  
  154.         if #parts >= 4 then
  155.             local v1PositionIndex, v1TexCoordIndex, v1NormalIndex = string_match(parts[2], "(%d+)/?(%d*)/?(%d*)")
  156.             local v3PositionIndex, v3TexCoordIndex, v3NormalIndex = string_match(parts[3], "(%d+)/?(%d*)/?(%d*)")
  157.  
  158.             v1PositionIndex, v1TexCoordIndex, v1NormalIndex = tonumber(v1PositionIndex), tonumber(v1TexCoordIndex), tonumber(v1NormalIndex)
  159.             v3PositionIndex, v3TexCoordIndex, v3NormalIndex = tonumber(v3PositionIndex), tonumber(v3TexCoordIndex), tonumber(v3NormalIndex)
  160.  
  161.             for i = 4, #parts do
  162.                 local v2PositionIndex, v2TexCoordIndex, v2NormalIndex = string_match(parts[i], "(%d+)/?(%d*)/?(%d*)")
  163.                 v2PositionIndex, v2TexCoordIndex, v2NormalIndex = tonumber(v2PositionIndex), tonumber(v2TexCoordIndex), tonumber(v2NormalIndex)
  164.  
  165.                 local v1 = { pos = nil, u = nil, v = nil, normal = nil }
  166.                 local v2 = { pos = nil, u = nil, v = nil, normal = nil }
  167.                 local v3 = { pos = nil, u = nil, v = nil, normal = nil }
  168.                 -- local v1 = { pos_index = nil, pos = nil, u = nil, v = nil, normal = nil }
  169.                 -- local v2 = { pos_index = nil, pos = nil, u = nil, v = nil, normal = nil }
  170.                 -- local v3 = { pos_index = nil, pos = nil, u = nil, v = nil, normal = nil }
  171.  
  172.                 v1.pos_index = v1PositionIndex
  173.                 v2.pos_index = v2PositionIndex
  174.                 v3.pos_index = v3PositionIndex
  175.  
  176.                 v1.pos = positions[v1PositionIndex]
  177.                 v2.pos = positions[v2PositionIndex]
  178.                 v3.pos = positions[v3PositionIndex]
  179.  
  180.                 if #texCoordsU > 0 then
  181.                     v1.u = texCoordsU[v1TexCoordIndex]
  182.                     v1.v = texCoordsV[v1TexCoordIndex]
  183.  
  184.                     v2.u = texCoordsU[v2TexCoordIndex]
  185.                     v2.v = texCoordsV[v2TexCoordIndex]
  186.  
  187.                     v3.u = texCoordsU[v3TexCoordIndex]
  188.                     v3.v = texCoordsV[v3TexCoordIndex]
  189.                 end
  190.  
  191.                 if #normals > 0 then
  192.                     v1.normal = normals[v1NormalIndex]
  193.                     v2.normal = normals[v2NormalIndex]
  194.                     v3.normal = normals[v3NormalIndex]
  195.                 end
  196.  
  197.                 triangleList [#triangleList + 1] = v1
  198.                 triangleList [#triangleList + 1] = v2
  199.                 triangleList [#triangleList + 1] = v3
  200.  
  201.                 v3PositionIndex, v3TexCoordIndex, v3NormalIndex = v2PositionIndex, v2TexCoordIndex, v2NormalIndex
  202.             end
  203.         end
  204.  
  205.         coroutine_yield(false, "Processing faces", i * inverseFaceLineCount)
  206.     end
  207.  
  208.     if generateNormals then
  209.         local vertexNormals = {}
  210.         local triangleCount = #triangleList / 3
  211.         local inverseTriangleCount = 1 / triangleCount
  212.         for i = 1, triangleCount do
  213.             local a, b, c = triangleList[1+(i-1)*3+0], triangleList[1+(i-1)*3+1], triangleList[1+(i-1)*3+2]
  214.             local normal =  (c.pos - a.pos):cross(b.pos - a.pos):getNormalized()
  215.  
  216.             vertexNormals[a.pos_index] = vertexNormals[a.pos_index] or Vector()
  217.             vertexNormals[a.pos_index] = (vertexNormals[a.pos_index] + normal)
  218.  
  219.             vertexNormals[b.pos_index] = vertexNormals[b.pos_index] or Vector()
  220.             vertexNormals[b.pos_index] = (vertexNormals[b.pos_index] + normal)
  221.  
  222.             vertexNormals[c.pos_index] = vertexNormals[c.pos_index] or Vector()
  223.             vertexNormals[c.pos_index] = (vertexNormals[c.pos_index] + normal)
  224.             coroutine_yield(false, "Generating normals", i * inverseTriangleCount)
  225.         end
  226.  
  227.         local defaultNormal = Vector(0, 0, -1)
  228.  
  229.         local vertexCount = #triangleList
  230.         local inverseVertexCount = 1 / vertexCount
  231.         for i = 1, vertexCount do
  232.             local normal = vertexNormals[triangleList[i].pos_index] or defaultNormal
  233.             normal:normalize()
  234.             normals[i] = normal
  235.             triangleList[i].normal = normal
  236.             coroutine_yield(false, "Normalizing normals", i * inverseVertexCount)
  237.         end
  238.     end
  239.  
  240.     return triangleList
  241. end
  242.  
  243. return { ParseObj = ParseObj }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement