do local s_new_player = new_player print(new_player) function new_player(settings, ...) local this = s_new_player(settings, ...) this.portal_list = {} this.portal_list_va = {} this.portal_tf_prev = nil this.portal_tf_prev_delay = nil local s_calc_motion_trace = this.calc_motion_trace function this.calc_motion_trace(sec_current, sec_delta, ox, oy, oz, nx, ny, nz, ...) local tx1, ty1, tz1 = s_calc_motion_trace(sec_current, sec_delta, ox, oy, oz, nx, ny, nz, ...) if this.portal_tf_prev_delay and sec_current > this.portal_tf_prev_delay+0.02 then this.portal_tf_prev = nil this.portal_tf_prev_delay = nil end local tf = trace_portal_get_transform(math.floor(tx1), math.floor(ty1), math.floor(tz1)) if not tf then return tx1, ty1, tz1 end -- Prevent a jam if tf.idx == this.portal_tf_prev then return tx1, ty1, tz1 end this.portal_tf_prev_delay = sec_current this.portal_tf_prev = tf.idx print("TRANSFORM", tf.idx) -- Apply to position + velocity tx1, ty1, tz1, this.vx, this.vy, this.vz = trace_portal_transform( tf, tx1, ty1, tz1, this.vx, this.vy, this.vz) -- Adjust y value so we don't jam ourselves -- (compare dys, if non0->0 then set y to cy plus something) if tf[2][5] == 0 and tf[1][5] ~= 0 then if this.crouching then ty1 = tf[2][2] else ty1 = tf[2][2] - 0.5 end end -- Get camera direction local sya = math.sin(this.angy) local cya = math.cos(this.angy) local sxa = math.sin(this.angx) local cxa = math.cos(this.angx) local fwx,fwy,fwz = sya*cxa, sxa, cya*cxa -- Apply to camera _, _, _, fwx, fwy, fwz = trace_portal_transform( tf, 0, 0, 0, fwx, fwy, fwz, true) -- Apply roll this.sx, this.sy, this.sz = sxa*sya, -cxa, sxa*cya _, _, _, this.sx, this.sy, this.sz = trace_portal_transform( tf, 0, 0, 0, this.sx, this.sy, this.sz, true) local ds = math.sqrt(this.sx*this.sx + this.sy*this.sy + this.sz*this.sz) this.sx = this.sx / ds this.sy = this.sy / ds this.sz = this.sz / ds -- Set camera direction this.angy = math.atan2(fwx, fwz) this.angx = math.asin(fwy) return tx1, ty1, tz1 end local function render_portals(render_mode) local i for i=1,2 do local p = this.portal_list[i] if p then local other = this.portal_list[3-i] local cx, cy, cz = p[1], p[2], p[3] local dx, dy, dz = p[4], p[5], p[6] local sx, sy, sz = p[7], p[8], p[9] local hx = dy*sz-dz*sy local hy = dz*sx-dx*sz local hz = dx*sy-dy*sx cx = cx + 0.5 cy = cy + 0.5 cz = cz + 0.5 --print("PORTAL", cx, cy, cz, dx, dy, dz, sx, sy, sz, i) if not p.va then local cr,cg,cb if i == 1 then cr,cg,cb = 0,0.5,1 else cr,cg,cb = 1,0.5,0 end local doffs = 0.5+0.02 local rh = 1.5-0.12 local rs = 1.5-0.12 local x1 = cx - doffs*dx - rh*hx - rs*sx local y1 = cy - doffs*dy - rh*hy - rs*sy local z1 = cz - doffs*dz - rh*hz - rs*sz local x2 = cx - doffs*dx + rh*hx - rs*sx local y2 = cy - doffs*dy + rh*hy - rs*sy local z2 = cz - doffs*dz + rh*hz - rs*sz local x3 = cx - doffs*dx - rh*hx + rs*sx local y3 = cy - doffs*dy - rh*hy + rs*sy local z3 = cz - doffs*dz - rh*hz + rs*sz local x4 = cx - doffs*dx + rh*hx + rs*sx local y4 = cy - doffs*dy + rh*hy + rs*sy local z4 = cz - doffs*dz + rh*hz + rs*sz p.va = {} this.portal_list_va[i] = this.portal_list_va[i] or {} p.va.border = common.va_make({ {x1,y1,z1,cr,cg,cb,-dx,-dy,-dz}, {x3,y3,z3,cr,cg,cb,-dx,-dy,-dz}, {x2,y2,z2,cr,cg,cb,-dx,-dy,-dz}, {x4,y4,z4,cr,cg,cb,-dx,-dy,-dz}, {x2,y2,z2,cr,cg,cb,-dx,-dy,-dz}, {x3,y3,z3,cr,cg,cb,-dx,-dy,-dz}, }, this.portal_list_va[i].border, "3v,3c,3n") doffs = doffs+0.005 rh = rh-0.12 rs = rs-0.12 x1 = cx - doffs*dx - rh*hx - rs*sx y1 = cy - doffs*dy - rh*hy - rs*sy z1 = cz - doffs*dz - rh*hz - rs*sz x2 = cx - doffs*dx + rh*hx - rs*sx y2 = cy - doffs*dy + rh*hy - rs*sy z2 = cz - doffs*dz + rh*hz - rs*sz x3 = cx - doffs*dx - rh*hx + rs*sx y3 = cy - doffs*dy - rh*hy + rs*sy z3 = cz - doffs*dz - rh*hz + rs*sz x4 = cx - doffs*dx + rh*hx + rs*sx y4 = cy - doffs*dy + rh*hy + rs*sy z4 = cz - doffs*dz + rh*hz + rs*sz doffs = doffs - 1 local x5 = cx - doffs*dx - rh*hx - rs*sx local y5 = cy - doffs*dy - rh*hy - rs*sy local z5 = cz - doffs*dz - rh*hz - rs*sz local x6 = cx - doffs*dx + rh*hx - rs*sx local y6 = cy - doffs*dy + rh*hy - rs*sy local z6 = cz - doffs*dz + rh*hz - rs*sz local x7 = cx - doffs*dx - rh*hx + rs*sx local y7 = cy - doffs*dy - rh*hy + rs*sy local z7 = cz - doffs*dz - rh*hz + rs*sz local x8 = cx - doffs*dx + rh*hx + rs*sx local y8 = cy - doffs*dy + rh*hy + rs*sy local z8 = cz - doffs*dz + rh*hz + rs*sz cr = cr/2 cg = cg/2 cb = cb/2 p.va.stencil = common.va_make({ {x1,y1,z1}, {x3,y3,z3}, {x2,y2,z2}, {x4,y4,z4}, {x2,y2,z2}, {x3,y3,z3}, {x5,y5,z5}, {x7,y7,z7}, {x6,y6,z6}, {x8,y8,z8}, {x6,y6,z6}, {x7,y7,z7}, {x1,y1,z1}, {x3,y3,z3}, {x5,y5,z5}, {x7,y7,z7}, {x5,y5,z5}, {x3,y3,z3}, {x2,y2,z2}, {x6,y6,z6}, {x4,y4,z4}, {x8,y8,z8}, {x4,y4,z4}, {x6,y6,z6}, {x1,y1,z1}, {x5,y5,z5}, {x2,y2,z2}, {x6,y6,z6}, {x2,y2,z2}, {x5,y5,z5}, {x3,y3,z3}, {x4,y4,z4}, {x7,y7,z7}, {x8,y8,z8}, {x7,y7,z7}, {x4,y4,z4}, }, this.portal_list_va[i].stencil, "3v") end if (not p.va.box) and other and other.va then local radius = 10 local x1 = cx - radius*(0+hx+sx-dx) local y1 = cy - radius*(0+hy+sy-dy) local z1 = cz - radius*(0+hz+sz-dz) local x2 = cx - radius*(0-hx+sx-dx) local y2 = cy - radius*(0-hy+sy-dy) local z2 = cz - radius*(0-hz+sz-dz) local x3 = cx - radius*(0+hx-sx-dx) local y3 = cy - radius*(0+hy-sy-dy) local z3 = cz - radius*(0+hz-sz-dz) local x4 = cx - radius*(0-hx-sx-dx) local y4 = cy - radius*(0-hy-sy-dy) local z4 = cz - radius*(0-hz-sz-dz) local x5 = cx - radius*(0+hx+sx) local y5 = cy - radius*(0+hy+sy) local z5 = cz - radius*(0+hz+sz) local x6 = cx - radius*(0-hx+sx) local y6 = cy - radius*(0-hy+sy) local z6 = cz - radius*(0-hz+sz) local x7 = cx - radius*(0+hx-sx) local y7 = cy - radius*(0+hy-sy) local z7 = cz - radius*(0+hz-sz) local x8 = cx - radius*(0-hx-sx) local y8 = cy - radius*(0-hy-sy) local z8 = cz - radius*(0-hz-sz) local fr, fg, fb, fd = client.map_fog_get() fr = fr / 255.0 fg = fg / 255.0 fb = fb / 255.0 fr = fr / 2.0 fg = fg / 2.0 fb = fb / 2.0 --print(fr, fg, fb) p.va.box = common.va_make({ {x1,y1,z1,fr,fg,fb,-dx,-dy,-dz}, {x3,y3,z3,fr,fg,fb,-dx,-dy,-dz}, {x2,y2,z2,fr,fg,fb,-dx,-dy,-dz}, {x4,y4,z4,fr,fg,fb,-dx,-dy,-dz}, {x2,y2,z2,fr,fg,fb,-dx,-dy,-dz}, {x3,y3,z3,fr,fg,fb,-dx,-dy,-dz}, {x1,y1,z1,fr,fg,fb,sx,sy,sz}, {x2,y2,z2,fr,fg,fb,sx,sy,sz}, {x5,y5,z5,fr,fg,fb,sx,sy,sz}, {x6,y6,z6,fr,fg,fb,sx,sy,sz}, {x5,y5,z5,fr,fg,fb,sx,sy,sz}, {x2,y2,z2,fr,fg,fb,sx,sy,sz}, {x3,y3,z3,fr,fg,fb,-sx,-sy,-sz}, {x7,y7,z7,fr,fg,fb,-sx,-sy,-sz}, {x4,y4,z4,fr,fg,fb,-sx,-sy,-sz}, {x8,y8,z8,fr,fg,fb,-sx,-sy,-sz}, {x4,y4,z4,fr,fg,fb,-sx,-sy,-sz}, {x7,y7,z7,fr,fg,fb,-sx,-sy,-sz}, {x1,y1,z1,fr,fg,fb,hx,hy,hz}, {x5,y5,z5,fr,fg,fb,hx,hy,hz}, {x3,y3,z3,fr,fg,fb,hx,hy,hz}, {x7,y7,z7,fr,fg,fb,hx,hy,hz}, {x3,y3,z3,fr,fg,fb,hx,hy,hz}, {x5,y5,z5,fr,fg,fb,hx,hy,hz}, {x2,y2,z2,fr,fg,fb,-hx,-hy,-hz}, {x4,y4,z4,fr,fg,fb,-hx,-hy,-hz}, {x6,y6,z6,fr,fg,fb,-hx,-hy,-hz}, {x8,y8,z8,fr,fg,fb,-hx,-hy,-hz}, {x6,y6,z6,fr,fg,fb,-hx,-hy,-hz}, {x4,y4,z4,fr,fg,fb,-hx,-hy,-hz}, }, this.portal_list_va[i].box, "3v,3c,3n") -- Build front-to-back local x,y,z local r local l = {} local tf = {other, p} cx, cy, cz = p[1], p[2], p[3] local tcx, tcy, tcz = other[1], other[2], other[3] local tdx, tdy, tdz = other[4], other[5], other[6] local tsx, tsy, tsz = other[7], other[8], other[9] local thx = tdy*tsz-tdz*tsy local thy = tdz*tsx-tdx*tsz local thz = tdx*tsy-tdy*tsx hx = -hx hy = -hy hz = -hz tdx = -tdx tdy = -tdy tdz = -tdz local taxx = hx*thx + hy*tsx + hz*tdx local taxy = hx*thy + hy*tsy + hz*tdy local taxz = hx*thz + hy*tsz + hz*tdz local tayx = sx*thx + sy*tsx + sz*tdx local tayy = sx*thy + sy*tsy + sz*tdy local tayz = sx*thz + sy*tsz + sz*tdz local tazx = dx*thx + dy*tsx + dz*tdx local tazy = dx*thy + dy*tsy + dz*tdy local tazz = dx*thz + dy*tsz + dz*tdz --[[ taxx, taxy, taxz = 1, 0, 0 tayx, tayy, tayz = 0, 1, 0 tazx, tazy, tazz = 0, 0, 1 ]] --[[ taxx, taxy, taxz = -taxx, -taxy, -taxz tayx, tayy, tayz = -tayx, -tayy, -tayz tazx, tazy, tazz = -tazx, -tazy, -tazz ]] local function add_block(rx, ry, rz, t, tx, ty, tz) local x1 = rx local y1 = ry local z1 = rz local x2 = rx+1 local y2 = ry+1 local z2 = rz+1 local cr,cg,cb = t[2], t[3], t[4] cr = cr / 255.0 cg = cg / 255.0 cb = cb / 255.0 cr = cr / 1.5 cg = cg / 1.5 cb = cb / 1.5 -- FIXME: some dy~=0 cases fail local ALL_FACES = false if dy ~= 0 or tdy ~= 0 then ALL_FACES = true end if ALL_FACES or map_block_get(tx-tazx,ty-tazy,tz-tazz) == nil then --print("block", rx, ry, rz, cr, cg, cb) l[1+#l] = {x1,y1,z1,cr,cg,cb,0,0,-1} l[1+#l] = {x2,y1,z1,cr,cg,cb,0,0,-1} l[1+#l] = {x1,y2,z1,cr,cg,cb,0,0,-1} l[1+#l] = {x2,y2,z1,cr,cg,cb,0,0,-1} l[1+#l] = {x1,y2,z1,cr,cg,cb,0,0,-1} l[1+#l] = {x2,y1,z1,cr,cg,cb,0,0,-1} end if ALL_FACES or map_block_get(tx+tazx,ty+tazy,tz+tazz) == nil then l[1+#l] = {x1,y1,z2,cr,cg,cb,0,0,1} l[1+#l] = {x1,y2,z2,cr,cg,cb,0,0,1} l[1+#l] = {x2,y1,z2,cr,cg,cb,0,0,1} l[1+#l] = {x2,y2,z2,cr,cg,cb,0,0,1} l[1+#l] = {x2,y1,z2,cr,cg,cb,0,0,1} l[1+#l] = {x1,y2,z2,cr,cg,cb,0,0,1} end if ALL_FACES or map_block_get(tx-tayx,ty-tayy,tz-tayz) == nil then l[1+#l] = {x1,y1,z1,cr,cg,cb,0,-1,0} l[1+#l] = {x1,y1,z2,cr,cg,cb,0,-1,0} l[1+#l] = {x2,y1,z1,cr,cg,cb,0,-1,0} l[1+#l] = {x2,y1,z2,cr,cg,cb,0,-1,0} l[1+#l] = {x2,y1,z1,cr,cg,cb,0,-1,0} l[1+#l] = {x1,y1,z2,cr,cg,cb,0,-1,0} end if ALL_FACES or map_block_get(tx+tayx,ty+tayy,tz+tayz) == nil then l[1+#l] = {x1,y2,z1,cr,cg,cb,0,1,0} l[1+#l] = {x2,y2,z1,cr,cg,cb,0,1,0} l[1+#l] = {x1,y2,z2,cr,cg,cb,0,1,0} l[1+#l] = {x2,y2,z2,cr,cg,cb,0,1,0} l[1+#l] = {x1,y2,z2,cr,cg,cb,0,1,0} l[1+#l] = {x2,y2,z1,cr,cg,cb,0,1,0} end if ALL_FACES or map_block_get(tx-taxx,ty-taxy,tz-taxz) == nil then l[1+#l] = {x1,y1,z1,cr,cg,cb,-1,0,0} l[1+#l] = {x1,y2,z1,cr,cg,cb,-1,0,0} l[1+#l] = {x1,y1,z2,cr,cg,cb,-1,0,0} l[1+#l] = {x1,y2,z2,cr,cg,cb,-1,0,0} l[1+#l] = {x1,y1,z2,cr,cg,cb,-1,0,0} l[1+#l] = {x1,y2,z1,cr,cg,cb,-1,0,0} end if ALL_FACES or map_block_get(tx+taxx,ty+taxy,tz+taxz) == nil then l[1+#l] = {x2,y1,z1,cr,cg,cb,1,0,0} l[1+#l] = {x2,y1,z2,cr,cg,cb,1,0,0} l[1+#l] = {x2,y2,z1,cr,cg,cb,1,0,0} l[1+#l] = {x2,y2,z2,cr,cg,cb,1,0,0} l[1+#l] = {x2,y2,z1,cr,cg,cb,1,0,0} l[1+#l] = {x2,y1,z2,cr,cg,cb,1,0,0} end end for r=radius*3,1,-1 do for z=0,r do local az = math.abs(z) local ystep = r-az for y=-ystep,ystep do if ystep < 0 then break end -- Get abs values for calculation local ay = math.abs(y) local xstep = r-(ay+az) for x=-xstep,xstep,2*xstep do if xstep < 0 then break end local ax = math.abs(x) local ma = math.max(math.max(ax,ay),az) local _ -- Ensure in range if ma <= radius and ax+ay+az == r then --if ax+ay+az == r then -- LET'S DO IT -- Get source coordinates local rx = cx + dx*z + hx*x + sx*y local ry = cy + dy*z + hy*x + sy*y local rz = cz + dz*z + hz*x + sz*y rx = math.floor(rx+0.5) ry = math.floor(ry+0.5) rz = math.floor(rz+0.5) -- Get target coordinates local tx = tcx + tdx*(z+1) + thx*x + tsx*y local ty = tcy + tdy*(z+1) + thy*x + tsy*y local tz = tcz + tdz*(z+1) + thz*x + tsz*y tx = math.floor(tx+0.5) ty = math.floor(ty+0.5) tz = math.floor(tz+0.5) --print("tf", tx, ty, tz, "->", rx, ry, rz) -- Get target block local b = map_block_get(tx,ty,tz) -- Add block if necessary if b then add_block(rx, ry, rz, b, tx, ty, tz) end end if xstep == 0 then break end end end end end p.va.scene = common.va_make(l, this.portal_list_va[i].scene, "3v,3c,3n") end this.portal_list_va[i] = p.va client.va_render_global(p.va.border, 0, 0, 0, 0, 0, 0, 1) if other and other.va and other.va.scene then -- Mark stencil region client.gfx_stencil_test(true) client.gfx_stencil_func("1", 2, 255) client.gfx_stencil_op(";;=") client.va_render_global(p.va.stencil, 0, 0, 0, 0, 0, 0, 1, nil, "10") -- Clear depth -- FIXME: engine needs support for glDepthFunc(GL_ALWAYS) -- (ATM we have to generate the block list back-to-front) client.gfx_stencil_func("==", 2, 255) client.gfx_stencil_op(";;;") client.gfx_depth_test(false) client.va_render_global(p.va.box, 0, 0, 0, 0, 0, 0, 1) client.va_render_global(p.va.scene, 0, 0, 0, 0, 0, 0, 1) client.gfx_depth_test(true) -- Clear stencil region client.gfx_stencil_func("1", 0, 255) client.gfx_stencil_op("===") client.va_render_global(p.va.stencil, 0, 0, 0, 0, 0, 0, 1, nil, "10") client.gfx_stencil_func("1", 0, 255) client.gfx_stencil_op(";;;") client.gfx_stencil_test(false) end end end end local s_render = this.render function this.render(render_mode, ...) if render_mode == nil then render_portals(render_mode) end local ret = s_render(render_mode, ...) return ret end return this end end