New line algo for lights

develop
Warmist 2013-06-23 12:20:35 +03:00
parent eb999cd0ad
commit 446b4b9d50
3 changed files with 126 additions and 9 deletions

@ -114,6 +114,19 @@ public:
virtual bool uses_opengl() { virtual bool uses_opengl() {
return parent->uses_opengl(); return parent->uses_opengl();
}; };
void invalidateRect(int32_t x,int32_t y,int32_t w,int32_t h)
{
for(int i=x;i<x+w;i++)
for(int j=y;j<y+h;j++)
{
int index=i*df::global::gps->dimy + j;
screen_old[index*4]=screen[index*4]+1;
}
};
void invalidate()
{
invalidateRect(0,0,df::global::gps->dimx,df::global::gps->dimy);
};
protected: protected:
renderer* parent; renderer* parent;
}; };

@ -185,6 +185,30 @@ static int setCell(lua_State* L)
r->backOffset[id]=bo; r->backOffset[id]=bo;
return 0; return 0;
} }
static int invalidate(lua_State* L)
{
if(current_mode!=MODE_LUA)
return 0;
renderer_lua* r=reinterpret_cast<renderer_lua*>(df::global::enabler->renderer);
if(lua_gettop(L)==0)
{
r->invalidate();
}
else
{
int x,y,w,h;
lua_getfield(L,1,"x");
x=lua_tonumber(L,-1);lua_pop(L,1);
lua_getfield(L,1,"y");
y=lua_tonumber(L,-1);lua_pop(L,1);
lua_getfield(L,1,"w");
w=lua_tonumber(L,-1);lua_pop(L,1);
lua_getfield(L,1,"h");
h=lua_tonumber(L,-1);lua_pop(L,1);
r->invalidateRect(x,y,w,h);
}
return 0;
}
bool isEnabled() bool isEnabled()
{ {
return current_mode==MODE_LUA; return current_mode==MODE_LUA;
@ -200,6 +224,7 @@ DFHACK_PLUGIN_LUA_COMMANDS {
DFHACK_LUA_COMMAND(getCell), DFHACK_LUA_COMMAND(getCell),
DFHACK_LUA_COMMAND(setCell), DFHACK_LUA_COMMAND(setCell),
DFHACK_LUA_COMMAND(getGridsSize), DFHACK_LUA_COMMAND(getGridsSize),
DFHACK_LUA_COMMAND(invalidate),
DFHACK_LUA_END DFHACK_LUA_END
}; };
static command_result rendermax(color_ostream &out, vector <string> & parameters) static command_result rendermax(color_ostream &out, vector <string> & parameters)

@ -50,7 +50,82 @@ function lightPassable(shape)
return true return true
end end
end end
function LightOverlay:placeLightFov(pos,radius,color,f,rays) function circle(xm, ym,r,plot)
local x = -r
local y = 0
local err = 2-2*r -- /* II. Quadrant */
repeat
plot(xm-x, ym+y);--/* I. Quadrant */
plot(xm-y, ym-x);--/* II. Quadrant */
plot(xm+x, ym-y);--/* III. Quadrant */
plot(xm+y, ym+x);--/* IV. Quadrant */
r = err;
if (r <= y) then
y=y+1
err =err+y*2+1; --/* e_xy+e_y < 0 */
end
if (r > x or err > y) then
x=x+1
err =err+x*2+1; --/* e_xy+e_x > 0 or no 2nd y-step */
end
until (x >= 0);
end
function line(x0, y0, x1, y1,plot)
local dx = math.abs(x1-x0)
local dy = math.abs(y1-y0)
local sx,sy
if x0 < x1 then sx = 1 else sx = -1 end
if y0 < y1 then sy = 1 else sy = -1 end
local err = dx-dy
while true do
if not plot(x0,y0) then
return
end
if x0 == x1 and y0 == y1 then
break
end
local e2 = 2*err
if e2 > -dy then
err = err - dy
x0 = x0 + sx
end
if x0 == x1 and y0 == y1 then
if not plot(x0,y0) then
return
end
break
end
if e2 < dx then
err = err + dx
y0 = y0 + sy
end
end
end
function LightOverlay:placeLightFov(pos,radius,color,f)
f=f or falloff
local vp=self:getViewport()
local map = self.df_layout.map
local ray=function(tx,ty)
local setTile=function(x,y)
if x>0 and y>0 and x<=map.width and y<=map.height then
local dtsq=(pos.x-x)*(pos.x-x)+(pos.y-y)*(pos.y-y)
local tile=x+y*map.width
local ncol=f(color,dtsq,radius)
local ocol=self.lightMap[tile] or {r=0,g=0,b=0}
ncol=blend(ncol,ocol)
self.lightMap[tile]=ncol
return self.ocupancy[tile]
end
return false
end
line(pos.x,pos.y,tx,ty,setTile)
end
circle(pos.x,pos.y,radius,ray)
end
function LightOverlay:placeLightFov2(pos,radius,color,f,rays)
f=f or falloff f=f or falloff
local raycount=rays or 25 local raycount=rays or 25
local vp=self:getViewport() local vp=self:getViewport()
@ -115,7 +190,9 @@ function LightOverlay:calculateLightLava()
local pos={x=i+vp.x1-1,y=j+vp.y1-1,z=vp.z} local pos={x=i+vp.x1-1,y=j+vp.y1-1,z=vp.z}
local pos2={x=i+vp.x1-1,y=j+vp.y1-1,z=vp.z-1} local pos2={x=i+vp.x1-1,y=j+vp.y1-1,z=vp.z-1}
local t1=dfhack.maps.getTileFlags(pos) local t1=dfhack.maps.getTileFlags(pos)
local shape=tile_attrs[dfhack.maps.getTileType(pos)].shape local tt=dfhack.maps.getTileType(pos)
if tt then
local shape=tile_attrs[tt].shape
local t2=dfhack.maps.getTileFlags(pos2) local t2=dfhack.maps.getTileFlags(pos2)
if (t1 and t1.liquid_type and t1.flow_size>0) or if (t1 and t1.liquid_type and t1.flow_size>0) or
(shape==df.tiletype_shape.EMPTY and t2 and t2.liquid_type and t2.flow_size>0) then (shape==df.tiletype_shape.EMPTY and t2 and t2.liquid_type and t2.flow_size>0) then
@ -124,6 +201,7 @@ function LightOverlay:calculateLightLava()
end end
end end
end end
end
end end
function LightOverlay:calculateLightSun() function LightOverlay:calculateLightSun()
local vp=self:getViewport() local vp=self:getViewport()
@ -193,7 +271,7 @@ function LightOverlay:render(dc)
self.lightMap=self.lightMap or {} self.lightMap=self.lightMap or {}
render.lockGrids() render.lockGrids()
df.global.gps.force_full_display_count=df.global.gps.force_full_display_count+1 render.invalidate({x=map.x1,y=map.y1,w=map.width,h=map.height})
render.resetGrids() render.resetGrids()
for i=map.x1,map.x2 do for i=map.x1,map.x2 do
for j=map.y1,map.y2 do for j=map.y1,map.y2 do
@ -212,8 +290,9 @@ end
function LightOverlay:onDismiss() function LightOverlay:onDismiss()
render.lockGrids() render.lockGrids()
render.resetGrids() render.resetGrids()
render.invalidate()
render.unlockGrids() render.unlockGrids()
df.global.gps.force_full_display_count=df.global.gps.force_full_display_count+1
end end
function LightOverlay:onInput(keys) function LightOverlay:onInput(keys)
if keys.LEAVESCREEN then if keys.LEAVESCREEN then