Advertisement
Guest User

122

a guest
Jan 23rd, 2017
104
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.22 KB | None | 0 0
  1. +local component = require("component")
  2. +local event = require("event")
  3. +local keyboard = require("keyboard")
  4. +local shell = require("shell")
  5. +local term = require("term")
  6. +local unicode = require("unicode")
  7. +local raytracer = require("raytracer")
  8. +
  9. +local args = shell.parse(...)
  10. +if #args < 1 then
  11. + io.write("Usage: print3d-view FILE [fov]\n")
  12. + os.exit(0)
  13. +end
  14. +
  15. +-- model loading
  16. +
  17. +local file, reason = io.open(args[1], "r")
  18. +if not file then
  19. + io.stderr:write("Failed opening file: " .. reason .. "\n")
  20. + os.exit(1)
  21. +end
  22. +
  23. +local rawdata = file:read("*all")
  24. +file:close()
  25. +local data, reason = load("return " .. rawdata)
  26. +if not data then
  27. + io.stderr:write("Failed loading model: " .. reason .. "\n")
  28. + os.exit(2)
  29. +end
  30. +data = data()
  31. +
  32. +-- set up raytracer
  33. +
  34. +local rt = raytracer.new()
  35. +rt.camera.position={-22+8,20+8,-22+8}
  36. +rt.camera.target={8,8,8}
  37. +rt.camera.fov=tonumber(args[2]) or 90
  38. +
  39. +local state
  40. +local function setState(value)
  41. + if state ~= value then
  42. + state = value
  43. + rt.model = {}
  44. + for _, shape in ipairs(data.shapes or {}) do
  45. + if not not shape.state == state then
  46. + table.insert(rt.model, shape)
  47. + end
  48. + end
  49. + if state and #rt.model < 1 then -- no shapes for active state
  50. + setState(false)
  51. + end
  52. + end
  53. +end
  54. +setState(false)
  55. +
  56. +-- set up gpu
  57. +
  58. +local gpu = component.gpu
  59. +local cfg, cbg
  60. +local function setForeground(color)
  61. + if cfg ~= color then
  62. + gpu.setForeground(color)
  63. + cfg = color
  64. + end
  65. +end
  66. +local function setBackground(color)
  67. + if cbg ~= color then
  68. + gpu.setBackground(color)
  69. + cbg = color
  70. + end
  71. +end
  72. +
  73. +-- helper functions
  74. +
  75. +local function vrotate(v, origin, angle)
  76. + local x, y = v[1]-origin[1], v[3]-origin[3]
  77. + local s = math.sin(angle)
  78. + local c = math.cos(angle)
  79. +
  80. + local rotx = x * c + y * s
  81. + local roty = -x * s + y * c
  82. + return {rotx+origin[1], v[2], roty+origin[3]}
  83. +end
  84. +
  85. +local function ambient(normal)
  86. + if math.abs(normal[1]) > 0.5 then
  87. + return 0.6
  88. + elseif math.abs(normal[3]) > 0.5 then
  89. + return 0.8
  90. + elseif normal[2] > 0 then
  91. + return 1.0
  92. + else
  93. + return 0.4
  94. + end
  95. +end
  96. +
  97. +local function hash(str)
  98. + local result = 7
  99. + for i=1,#str do
  100. + result = (result*31 + string.byte(str, i))%0xFFFFFFFF
  101. + end
  102. + return result
  103. +end
  104. +
  105. +local function multiply(color, brightness)
  106. + local r,b,g=(color/2^16)%256,(color/2^8)%256,color%256
  107. + r = r*brightness
  108. + g = g*brightness
  109. + b = b*brightness
  110. + return r*2^16+g*2^8+b
  111. +end
  112. +
  113. +local palette = {0x0000FF, 0x00FF00, 0x00FFFF, 0xFF0000, 0xFF00FF, 0xFFFF00, 0xFFFFFF}
  114. +
  115. +-- render model
  116. +while true do
  117. + setForeground(0x000000)
  118. + setBackground(0x000000)
  119. + local rx, ry = gpu.getResolution()
  120. + gpu.fill(1, 1, rx, ry, unicode.char(0x2580))
  121. +
  122. + rt:render(rx, ry*2, function(x, y, shape, normal)
  123. + local sx, sy = x, math.ceil(y / 2)
  124. + local ch, fg, bg = gpu.get(sx, sy)
  125. + local brightness = ambient(normal)
  126. + local color = multiply(data.palette and data.palette[shape.texture] or palette[hash(shape.texture or "") % #palette + 1], brightness)
  127. + if color == 0x000000 then return end
  128. + if y % 2 == 1 then
  129. + setBackground(bg)
  130. + setForeground(color)
  131. + else
  132. + setBackground(color)
  133. + setForeground(fg)
  134. + end
  135. + gpu.set(sx, sy, ch)
  136. + end)
  137. +
  138. + gpu.setForeground(0xFFFFFF)
  139. + gpu.setBackground(0x000000)
  140. +
  141. + gpu.set(1, ry, "[q] Quit [left/right] Rotate [space] Toggle state")
  142. + os.sleep(0.1) -- consume events that arrived in the meantime
  143. + while true do
  144. + local _,_,_,code=event.pull("key_down")
  145. + if code == keyboard.keys.q then
  146. + term.clear()
  147. + os.exit(0)
  148. + elseif code == keyboard.keys.space then
  149. + setState(not state)
  150. + break
  151. + elseif code == keyboard.keys.left then
  152. + local step = 10
  153. + if keyboard.isShiftDown() then step = 90 end
  154. + rt.camera.position = vrotate(rt.camera.position, rt.camera.target, -step/180*math.pi)
  155. + break
  156. + elseif code == keyboard.keys.right then
  157. + local step = 10
  158. + if keyboard.isShiftDown() then step = 90 end
  159. + rt.camera.position = vrotate(rt.camera.position, rt.camera.target, step/180*math.pi)
  160. + break
  161. + end
  162. + end
  163. +end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement