Skip to content

Instantly share code, notes, and snippets.

@fulmicoton
Created March 10, 2012 17:33
Show Gist options
  • Save fulmicoton/2012239 to your computer and use it in GitHub Desktop.
Save fulmicoton/2012239 to your computer and use it in GitHub Desktop.
poor man's 3d
W = 490
H = 315
load_image_into_canvas = (path, ctx, callback=((ctx)->))->
img = new Image()
img.onload = ->
ctx.drawImage img,0,0,W,H
callback ctx
img.src = path
render_mesh = (depth, dest, camera, callback=(->))->
depthp = depth.getImageData(0,0,W,H).data
dest.fillStyle = "rgba(0, 0, 0, 1.0)"
dest.fillRect 0,0,W,H
dest_img = dest.getImageData 0,0,W,H
destp = dest_img.data
h = 1.0/(255.0*15.0)
for i in [0...W]
for j in [0...H]
offset = (i + j*W) * 4
d = depthp[offset]
x = i + Math.ceil(d*camera.hx*5*i)
y = j + Math.ceil(d*camera.hy*5*j)
if 0 <= x < W and 0 <= y < H
dest_offset = (x + y*W) * 4
destp[dest_offset ] = 255
destp[dest_offset+1] = 255
destp[dest_offset+2] = 255
dest.putImageData dest_img, 0, 0
callback()
triangle = (p1,p2,p3)->
p1c
filter = (l, predicate)->
res = []
for x in l
if predicate x
res.push x
res
render_scene = (src, depth, dest, camera)->
# the poor man's 3d
img = src.getImageData 0,0,W,H
dest_img = dest.getImageData 0,0,W,H
depthp = depth.getImageData(0,0,W,H).data
dest_votes = dest.createImageData W,H
srcp = img.data
destp = dest_img.data
N = W*H*4
if camera?
for offset in [0...W*H*4] by 4
destp[offset+3] = 0
for i in [0...W]
for j in [0...H]
offset = (i + j*W) * 4
d = depthp[offset]
x = i + Math.ceil(d*camera.hx*i)
y = j + Math.ceil(d*camera.hy*j)
if 0 <= x < W and 0 <= y < H
dest_offset = (x + y*W) * 4
destp[dest_offset ] = srcp[offset]
destp[dest_offset+1] = srcp[offset+1]
destp[dest_offset+2] = srcp[offset+2]
destp[dest_offset+3] = 255
for offset in [0...W*H*4] by 4
if destp[offset + 3] == 0
c = 0
[r,g,b] = [0,0,0]
NEIGHBORS = [-W*4,W*4,-4,4]
for neighbor in NEIGHBORS
neighbor_offset = offset+neighbor
if 0 <= neighbor_offset < N
if destp[neighbor_offset+3] == 255
c += 1
r += destp[neighbor_offset+0]
g += destp[neighbor_offset+1]
b += destp[neighbor_offset+2]
if c>0
destp[offset] = Math.ceil(r/c)
destp[offset+1] = Math.ceil(g/c)
destp[offset+2] = Math.ceil(b/c)
destp[offset+3] = 255
else
for offset in [0...W*H*4] by 4
destp[offset+0] = 0
destp[offset+1] = 0
destp[offset+2] = 0
destp[offset+3] = 255
dest.putImageData dest_img, 0, 0
pipe = (functions...)->
if functions.length > 0
functions[0](-> pipe functions[1..]...)
animate = (img, depth)->
h = 0.2/(255.0*15.0)
CAMERAS = [
{ hx: h, hy: h},
{ hx: 0, hy: h},
{ hx: -h, hy: h},
{ hx: -h, hy: 0},
{ hx: -h, hy: -h},
{ hx: 0, hy: -h},
{ hx: h, hy: -h},
{ hx: h, hy: 0}
]
mesh = document.getElementById('mesh').getContext '2d'
result = document.getElementById('result').getContext '2d'
camera_id = 0
render_frame = ->
camera = CAMERAS[camera_id]
#render_mesh depth, mesh, camera
render_scene img, depth, result, camera
camera_id = (camera_id + 1) % CAMERAS.length
setInterval render_frame, 50
main = ->
img = document.getElementById('image').getContext '2d'
depth = document.getElementById('depth').getContext '2d'
pipe ( (callback)->load_image_into_canvas 'image.png', img, callback ),
( (callback)->load_image_into_canvas 'depth.png', depth, callback ),
( -> animate(img, depth) )
$ main
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment