Guest User

atobj.lua

a guest
Oct 9th, 2016
90
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 10.59 KB | None | 0 0
  1. -- OBJ model library 2.2
  2. -- ---------------------
  3. -- by Totoro and Xytabich (computercraft.ru)
  4.  
  5. local png = require("PNGImage")
  6.  
  7. atobj = {}
  8.  
  9. local vertex = {}
  10. local faces = {}
  11. local triangles = {}
  12.  
  13. local image
  14. local texCoords = {}
  15. local palette = {}
  16.  
  17. local frames = {}
  18.  
  19. local animFaces1 = {}
  20. local animFaces2 = {}
  21.  
  22. local color = {r = 1, g = 0, b = 0, a = 1}
  23. local position = {x = 0, y = 0, z = 0}
  24. local rotation = {x = 0, y = 0, z = 0}
  25. local scale = 1.0
  26.  
  27. local paletteColors = true
  28.  
  29. local function getVT(data)
  30. local v, t = data:match("(-?%d+)/(-?%d+)")
  31. return tonumber(v), tonumber(t) or nil
  32. end
  33.  
  34. local function round(v)
  35. local r = math.floor(v)
  36. if v-0.5 > r then return math.ceil(v)
  37. else return r end
  38. end
  39.  
  40. local function inBounds(u, v) -- trim the number to the borders of 0-1
  41. if u > 1 then
  42. local a, b = math.modf(u)
  43. u = b
  44. elseif u < 0 then
  45. local a, b = math.modf(u)
  46. u = 1+b
  47. end
  48. if v > 1 then
  49. local a, b = math.modf(v)
  50. v = b
  51. elseif v < 0 then
  52. local a, b = math.modf(v)
  53. v = 1+b
  54. end
  55. return u, v
  56. end
  57.  
  58. local function getFaceColor(t1, t2, t3)
  59. if (image == nil) or (t1 > #texCoords) or
  60. (t2 > #texCoords) or (t3 > #texCoords) then return nil
  61. else
  62. local u,v = table.unpack(texCoords[t1])
  63. local w,h = image:getSize()
  64. w=w-1 h=h-1
  65. if paletteColors then
  66. local r,g,b,a = image:getPixel(round(u*w), round((1-v)*h))
  67. if r == nil then return nil end
  68. return r/255, g/255, b/255, a/255
  69. else -- average color of 3 points - алгоритм для ленивых
  70. local r1,g1,b1,a1 = image:getPixel(round(u*w), round((1-v)*h))
  71. if r1 == nil then return nil end
  72. u,v = table.unpack(texCoords[t2])
  73. local r2,g2,b2,a2 = image:getPixel(round(u*w), round((1-v)*h))
  74. if r2 == nil then return nil end
  75. u,v = table.unpack(texCoords[t3])
  76. local r3,g3,b3,a3 = image:getPixel(round(u*w), round((1-v)*h))
  77. if r3 == nil then return nil end
  78. return ((r1+r2+r3)/3)/255, ((g1+g2+g3)/3)/255, ((b1+b2+b3)/3)/255, ((a1+a2+a3)/3)/255
  79. end
  80. end
  81. end
  82.  
  83. local function getPaletteIndex(r,g,b,a)
  84. for i=1, #palette do
  85. local pr,pg,pb,pa = table.unpack(palette[i])
  86. if (r==pr) and (g==pg) and (b==pb) and (a==pa) then
  87. return i
  88. end
  89. end
  90.  
  91. table.insert(palette, {r,g,b,a})
  92. return #palette
  93. end
  94.  
  95. local function getPaletteColor(i)
  96. if (i < 1) or (i > #palette) then return 1,1,1,1
  97. else return table.unpack(palette[i]) end
  98. end
  99.  
  100. local function lerp(v1, v2, t)
  101. local v = {0,0,0}
  102. v[1] = (1-t)*v1[1] + t*v2[1];
  103. v[2] = (1-t)*v1[2] + t*v2[2];
  104. v[3] = (1-t)*v1[3] + t*v2[3];
  105. return v
  106. end
  107.  
  108. local function findTab(tab, i)
  109. for n,v in pairs(tab) do
  110. if v ~= nil then
  111. if v[1] == i then return v[2] end
  112. end
  113. end
  114.  
  115. return nil
  116. end
  117.  
  118. local function getPointRotation(v)
  119. local x,y,z = table.unpack(v)
  120. local rx,ry,rz = 0,0,0
  121. rx = x*math.cos(rotation.y)+z*math.sin(rotation.y)+x*math.cos(rotation.z)-y*math.sin(rotation.z)
  122. ry = y*math.cos(rotation.x)+z*math.sin(rotation.x)+x*math.sin(rotation.z)+y*math.cos(rotation.z)
  123. rz = -y*math.sin(rotation.x)+z*math.cos(rotation.x)-x*math.sin(rotation.y)+z*math.cos(rotation.y)
  124. return {rx,ry,rz}
  125. end
  126.  
  127. local function updateTransform()
  128. for n, triangle in pairs(triangles) do
  129. local v1 = getPointRotation(triangle.vertexes[1])
  130. local v2 = getPointRotation(triangle.vertexes[2])
  131. local v3 = getPointRotation(triangle.vertexes[3])
  132. triangle.setVertex(1, v1[1]*scale + position.x, v1[2]*scale + position.y, v1[3]*scale + position.z)
  133. triangle.setVertex(2, v2[1]*scale + position.x, v2[2]*scale + position.y, v2[3]*scale + position.z)
  134. triangle.setVertex(3, v3[1]*scale + position.x, v3[2]*scale + position.y, v3[3]*scale + position.z)
  135. end
  136. end
  137.  
  138. atobj.loadTexture = function(filename)
  139. image = png.newFromFile(filename);
  140. end
  141.  
  142. atobj.load = function(filename)
  143. file = io.open(filename, "r")
  144. if file ~= nil then
  145. vertex = {}
  146.  
  147. for line in file:lines() do
  148. if line ~= nil and line ~= '' then
  149. local key, a, b, c, d = line:match("(%S+)%s+(%S+)%s+(%S+)%s+(%S+)%s*(%S*)")
  150.  
  151. -- load vertex data / skip normals
  152. if key == 'v' then
  153. local x, y, z = tonumber(a), tonumber(b), tonumber(c)
  154. table.insert(vertex, {x,y,z})
  155.  
  156. -- load texture data
  157. elseif key == "vt" then
  158. local u, v = tonumber(a), tonumber(b)
  159. table.insert(texCoords, table.pack(inBounds(u, v)))
  160.  
  161. -- load faces data
  162. elseif key == 'f' then
  163. local v1, t1 = getVT(a)
  164. local v2, t2 = getVT(b)
  165. local v3, t3 = getVT(c)
  166. if v1 < 0 then
  167. local len = #vertex + 1
  168. v1, v2, v3 = len + v1, len + v2, len + v3
  169. end
  170. local p = 0
  171. if t1 ~= nil then
  172. r,g,b,a = getFaceColor(t1, t2, t3)
  173. if r ~= nil then
  174. p = getPaletteIndex(r,g,b,a)
  175. end
  176. end
  177. table.insert(faces, {vertex[v1], vertex[v2], vertex[v3], p})
  178. end
  179. end
  180. end
  181. file:close()
  182. else
  183. error("[OBJ.load] File not found!")
  184. end
  185. end
  186.  
  187. atobj.loadFrame = function(filename) -- из базового кадра берутся значения в случае отсутствия их в таблице измененных вершин
  188. file = io.open(filename, "r")
  189. if file ~= nil then
  190. local frame = {}
  191. local frameVertex = {}
  192. local frameFaces = {}
  193. local lastVertex = 1
  194. local lastFace = 1
  195. for line in file:lines() do
  196. if line ~= nil and line ~= '' then
  197. local key, a, b, c, d = line:match("(%S+)%s+(%S+)%s+(%S+)%s+(%S+)%s*(%S*)")
  198.  
  199. -- load vertex data
  200. if key == 'v' then
  201. local x, y, z = tonumber(a), tonumber(b), tonumber(c)
  202. local vx, vy, vz = table.unpack(vertex[lastVertex])
  203. if (x ~= vx) or (y ~= vy) or (z ~= vz) then
  204. table.insert(frameVertex, {lastVertex, {x,y,z}})
  205. end
  206. lastVertex = lastVertex+1
  207.  
  208. -- load faces data
  209. elseif key == 'f' then
  210. local v1 = getVT(a)
  211. local v2 = getVT(b)
  212. local v3 = getVT(c)
  213. if v1 < 0 then
  214. local len = #vertex + 1
  215. v1, v2, v3 = len + v1, len + v2, len + v3
  216. end
  217. local fv1 = findTab(frameVertex,v1)
  218. local fv2 = findTab(frameVertex,v2)
  219. local fv3 = findTab(frameVertex,v3)
  220. if (fv1 ~= nil) or (fv2 ~= nil) or (fv3 ~= nil) then
  221. table.insert(frameFaces, {lastFace, {fv1, fv2, fv3}})
  222. end
  223. lastFace = lastFace+1
  224. end
  225. end
  226. end
  227. table.insert(frames, frameFaces)
  228. file:close()
  229. else
  230. error("[OBJ.loadFrame] File not found!")
  231. end
  232. end
  233.  
  234. atobj.setColor = function(r, g, b, a)
  235. color.r = r; color.g = g; color.b = b; color.a = a or 1;
  236. end
  237. atobj.setPosition = function(x, y, z)
  238. position.x = x; position.y = y; position.z = z
  239.  
  240. updateTransform()
  241. end
  242. atobj.setRotation = function(x, y, z)
  243. rx = x; ry = y; rz = z
  244.  
  245. if rx < 0 then rx = 360+rx
  246. elseif rx > 360 then rx = rx-360 end
  247. if ry < 0 then ry = 360+ry
  248. elseif ry > 360 then ry = ry-360 end
  249. if rz < 0 then rz = 360+rz
  250. elseif rz > 360 then rx = rz-360 end
  251.  
  252. rotation.x = math.rad(rx); rotation.y = math.rad(ry); rotation.z = math.rad(rz)
  253.  
  254. updateTransform()
  255. end
  256. atobj.setScale = function(s)
  257. scale = s
  258.  
  259. updateTransform()
  260. end
  261.  
  262. atobj.getColor = function()
  263. return {color.r, color.g, color.b, color.a}
  264. end
  265. atobj.getPosition = function()
  266. return {position.x, position.y, position.z}
  267. end
  268. atobj.getRotation = function()
  269. return {math.deg(rotation.x), math.deg(rotation.y), math.deg(rotation.z)}
  270. end
  271. atobj.getScale = function()
  272. return scale
  273. end
  274. atobj.getFramesNum = function()
  275. return #frames
  276. end
  277.  
  278. atobj.usePalette = function(use)
  279. if use ~= nil then paletteColors = use
  280. else return paletteColors end
  281. end
  282.  
  283. atobj.draw = function(glasses)
  284. local count = 0
  285. for n, face in pairs(faces) do
  286. local triangle = glasses.addTriangle3D()
  287. local vertexes = {}
  288. table.insert(vertexes, table.pack(face[1][1], face[1][2], face[1][3]))
  289. table.insert(vertexes, table.pack(face[2][1], face[2][2], face[2][3]))
  290. table.insert(vertexes, table.pack(face[3][1], face[3][2], face[3][3]))
  291. r,g,b,a = getPaletteColor(face[4])
  292. triangle.setColor(color.r*r, color.g*g, color.b*b)
  293. triangle.setAlpha(color.a*a)
  294. triangle.setVisibleThroughObjects(false)
  295. triangle.vertexes = vertexes
  296. table.insert(triangles, n, triangle)
  297. ---
  298. count = count + 1
  299. if count > 18 then count = 0; os.sleep(0.1) end
  300. end
  301.  
  302. updateTransform()
  303. end
  304.  
  305. atobj.setFrame = function(fn)
  306. if (fn ~= 0) and (frames[fn] == nil) then return false end
  307. animFaces1 = {} -- vertexes
  308. animFaces2 = {} -- vertexes, triangleNumber
  309. if fn == 0 then
  310. for i=1, #frames do
  311. table.insert(animFaces2, table.pack(faces[i][1], faces[i][2], faces[i][3], i))
  312. table.insert(animFaces1, triangles[i].vertexes)
  313. end
  314. else
  315. for n, tf in pairs(frames[fn]) do
  316. local i, f = table.unpack(tf)
  317. table.insert(animFaces2, table.pack(f[1] or triangles[i].vertexes[1],
  318. f[2] or triangles[i].vertexes[2], f[3] or triangles[i].vertexes[3], i))
  319. table.insert(animFaces1, triangles[i].vertexes)
  320. end
  321. end
  322. return true
  323. end
  324.  
  325. atobj.animate = function(t)
  326. for n, f in pairs(animFaces2) do
  327. v1 = lerp(animFaces1[n][1], f[1], t)
  328. v2 = lerp(animFaces1[n][2], f[2], t)
  329. v3 = lerp(animFaces1[n][3], f[3], t)
  330. local vertexes = {}
  331. table.insert(vertexes, table.pack(v1[1], v1[2], v1[3]))
  332. table.insert(vertexes, table.pack(v2[1], v2[2], v2[3]))
  333. table.insert(vertexes, table.pack(v3[1], v3[2], v3[3]))
  334. triangles[f[4]].setVertex(1, getPointRotation(vertexes[1])[1]*scale + position.x,
  335. getPointRotation(vertexes[1])[2]*scale + position.y, getPointRotation(vertexes[1])[3]*scale + position.z)
  336. triangles[f[4]].setVertex(2, getPointRotation(vertexes[2])[1]*scale + position.x,
  337. getPointRotation(vertexes[2])[2]*scale + position.y, getPointRotation(vertexes[2])[3]*scale + position.z)
  338. triangles[f[4]].setVertex(3, getPointRotation(vertexes[3])[1]*scale + position.x,
  339. getPointRotation(vertexes[3])[2]*scale + position.y, getPointRotation(vertexes[3])[3]*scale + position.z)
  340. triangles[f[4]].vertexes = vertexes
  341. end
  342. end
  343.  
  344. atobj.getVertexNum = function()
  345. return #vertex
  346. end
  347. atobj.getPolyNum = function()
  348. return #faces
  349. end
  350.  
  351. return atobj
Add Comment
Please, Sign In to add comment