Major rewrite of opacity calculation.

develop
Warmist 2013-06-25 00:59:32 +03:00
parent cb767531cf
commit 4d9b7bd23d
3 changed files with 266 additions and 188 deletions

@ -4,12 +4,13 @@
#include <string> #include <string>
#include <math.h> #include <math.h>
#include "Types.h"
#include "LuaTools.h" #include "LuaTools.h"
#include "modules/Gui.h" #include "modules/Gui.h"
#include "modules/Screen.h" #include "modules/Screen.h"
#include "modules/Maps.h" #include "modules/Maps.h"
#include "modules/Units.h" #include "modules/Units.h"
#include "df/graphic.h" #include "df/graphic.h"
@ -64,7 +65,7 @@ rect2d getMapViewport()
if(menu_pos < 2) menu_x = menu_x1; if(menu_pos < 2) menu_x = menu_x1;
view_rb = menu_x; view_rb = menu_x;
} }
return mkrect_wh(1,1,view_rb,view_height+1); return mkrect_wh(1,1,view_rb,view_height);
} }
lightingEngineViewscreen::lightingEngineViewscreen(renderer_light* target):lightingEngine(target) lightingEngineViewscreen::lightingEngineViewscreen(renderer_light* target):lightingEngine(target)
{ {
@ -225,6 +226,10 @@ void lightingEngineViewscreen::updateWindow()
myRenderer->invalidate(); myRenderer->invalidate();
return; return;
} }
//if(showOcupancy)
//std::swap(ocupancy,myRenderer->lightGrid);
//else
std::swap(lightMap,myRenderer->lightGrid); std::swap(lightMap,myRenderer->lightGrid);
rect2d vp=getMapViewport(); rect2d vp=getMapViewport();
@ -269,6 +274,14 @@ void addPlant(const std::string& id,std::map<int,lightSource>& map,const lightSo
map[nId]=v; map[nId]=v;
} }
} }
matLightDef* lightingEngineViewscreen::getMaterial(int matType,int matIndex)
{
auto it=matDefs.find(std::make_pair(matType,matIndex));
if(it!=matDefs.end())
return &it->second;
else
return NULL;
}
void lightingEngineViewscreen::applyMaterial(int tileId,const matLightDef& mat,float size) void lightingEngineViewscreen::applyMaterial(int tileId,const matLightDef& mat,float size)
{ {
if(mat.isTransparent) if(mat.isTransparent)
@ -280,10 +293,10 @@ void lightingEngineViewscreen::applyMaterial(int tileId,const matLightDef& mat,f
} }
bool lightingEngineViewscreen::applyMaterial(int tileId,int matType,int matIndex,float size,const matLightDef* def) bool lightingEngineViewscreen::applyMaterial(int tileId,int matType,int matIndex,float size,const matLightDef* def)
{ {
auto it=matDefs.find(std::make_pair(matType,matIndex)); matLightDef* m=getMaterial(matType,matIndex);
if(it!=matDefs.end()) if(m)
{ {
applyMaterial(tileId,it->second,size); applyMaterial(tileId,*m,size);
return true; return true;
} }
else if(def) else if(def)
@ -292,207 +305,223 @@ bool lightingEngineViewscreen::applyMaterial(int tileId,int matType,int matIndex
} }
return false; return false;
} }
static size_t max_list_size = 100000; // Avoid iterating over huge lists lightCell lightingEngineViewscreen::propogateSun(MapExtras::Block* b, int x,int y,const lightCell& in,bool lastLevel)
void lightingEngineViewscreen::doOcupancyAndLights()
{ {
// TODO better curve (+red dawn ?) const lightCell matStairCase(0.9f,0.9f,0.9f);
float daycol = abs((*df::global::cur_year_tick % 1200) - 600.0) / 400.0; lightCell ret=in;
lightCell sky_col(daycol, daycol, daycol); coord2d innerCoord(x,y);
lightSource sky(sky_col, 15); df::tiletype type = b->tiletypeAt(innerCoord);
df::tile_designation d = b->DesignationAt(innerCoord);
lightSource candle(lightCell(0.96f,0.84f,0.03f),5); //df::tile_occupancy o = b->OccupancyAt(innerCoord);
lightSource torch(lightCell(0.9f,0.75f,0.3f),8); df::tiletype_shape shape = ENUM_ATTR(tiletype,shape,type);
df::tiletype_shape_basic basic_shape = ENUM_ATTR(tiletype_shape, basic_shape, shape);
//perfectly blocking material DFHack::t_matpair mat=b->staticMaterialAt(innerCoord);
matLightDef matWall(lightCell(0,0,0)); df::tiletype_material tileMat= ENUM_ATTR(tiletype,material,type);
rect2d vp=getMapViewport();
matLightDef* lightDef;
if(tileMat==df::tiletype_material::FROZEN_LIQUID)
lightDef=&matIce;
else
lightDef=getMaterial(mat.mat_type,mat.mat_index);
if(!lightDef || !lightDef->isTransparent)
lightDef=&matWall;
if(basic_shape==df::tiletype_shape_basic::Wall)
{
ret*=lightDef->transparency;
}
else if(basic_shape==df::tiletype_shape_basic::Floor || basic_shape==df::tiletype_shape_basic::Ramp || shape==df::tiletype_shape::STAIR_UP)
{
if(!lastLevel)
ret*=lightDef->transparency; //TODO modify because floors have less material
}
else if(shape==df::tiletype_shape::STAIR_DOWN || shape==df::tiletype_shape::STAIR_UPDOWN)
{
ret*=matStairCase;
}
if(d.bits.liquid_type == df::enums::tile_liquid::Water && d.bits.flow_size)
{
ret *=matWater.transparency;// (lightCell(1,1,1) - (lightCell(1,1,1) - matWater)*((float)d.bits.flow_size/7.0f));
}
else if(d.bits.liquid_type == df::enums::tile_liquid::Magma && d.bits.flow_size > 3)
{
ret *=matLava.transparency;
}
return ret;
}
coord2d lightingEngineViewscreen::worldToViewportCoord(const coord2d& in,const rect2d& r,const coord2d& window2d)
{
return in-window2d+r.first;
}
bool lightingEngineViewscreen::isInViewport(const coord2d& in,const rect2d& r)
{
if(in.x>=r.first.x && in.y>=r.first.y && in.x<r.second.x && in.y<r.second.y)
return true;
return false;
}
static size_t max_list_size = 100000; // Avoid iterating over huge lists
void lightingEngineViewscreen::doSun(const lightSource& sky,MapExtras::MapCache& map)
{
//TODO fix this mess
int window_x=*df::global::window_x; int window_x=*df::global::window_x;
int window_y=*df::global::window_y; int window_y=*df::global::window_y;
coord2d window2d(window_x,window_y);
int window_z=*df::global::window_z; int window_z=*df::global::window_z;
int vpW=vp.second.x-vp.first.x; rect2d vp=getMapViewport();
int vpH=vp.second.y-vp.first.y; coord2d vpSize=rect_size(vp);
int endBlockx = (window_x+vpW)/16; rect2d blockVp;
int endBlocky = (window_y+vpH)/16; blockVp.first=window2d/16;
if(endBlockx >= df::global::world->map.x_count_block) endBlockx = df::global::world->map.x_count_block-1; blockVp.second=(window2d+vpSize)/16;
if(endBlocky >= df::global::world->map.y_count_block) endBlocky = df::global::world->map.y_count_block-1; blockVp.second.x=std::min(blockVp.second.x,(int16_t)df::global::world->map.x_count_block);
for(int blockx=window_x/16;blockx<=endBlockx;blockx++) blockVp.second.y=std::min(blockVp.second.y,(int16_t)df::global::world->map.y_count_block);
for(int blocky=window_y/16;blocky<=endBlocky;blocky++) //endof mess
for(int blockX=blockVp.first.x;blockX<=blockVp.second.x;blockX++)
for(int blockY=blockVp.first.y;blockY<=blockVp.second.y;blockY++)
{ {
lightCell cellArray[16][16]; lightCell cellArray[16][16];
for(int block_x = 0; block_x < 16; block_x++) for(int block_x = 0; block_x < 16; block_x++)
for(int block_y = 0; block_y < 16; block_y++) for(int block_y = 0; block_y < 16; block_y++)
cellArray[block_x][block_y] = sky.power;
int emptyCell=0;
for(int z=df::global::world->map.z_count-1;z>=window_z && emptyCell<256;z--)
{ {
cellArray[block_x][block_y] = sky_col; MapExtras::Block* b=map.BlockAt(DFCoord(blockX,blockY,z));
} if(!b)
int totalBlank = 0; continue;
int topLevel = df::global::world->map.z_count-1; emptyCell=0;
for(int ZZ = topLevel; (ZZ >= window_z) && totalBlank < 256; ZZ--)
{
df::map_block* block=Maps::getBlock(blockx,blocky,ZZ);
totalBlank = 0;
if(block)
for(int block_x = 0; block_x < 16; block_x++) for(int block_x = 0; block_x < 16; block_x++)
for(int block_y = 0; block_y < 16; block_y++) for(int block_y = 0; block_y < 16; block_y++)
{ {
df::tiletype type = block->tiletype[block_x][block_y]; lightCell& curCell=cellArray[block_x][block_y];
df::tile_designation d = block->designation[block_x][block_y]; curCell=propogateSun(b,block_x,block_y,curCell,z==window_z);
df::tile_occupancy o = block->occupancy[block_x][block_y]; if(curCell.dot(curCell)<0.003f)
df::tiletype_shape shape = ENUM_ATTR(tiletype,shape,type); emptyCell++;
df::tiletype_shape_basic basic_shape = ENUM_ATTR(tiletype_shape, basic_shape, shape);
if(basic_shape==df::tiletype_shape_basic::Wall)
{
cellArray[block_x][block_y]=lightCell(0,0,0);
}
else if(basic_shape==df::tiletype_shape_basic::Floor || basic_shape==df::tiletype_shape_basic::Ramp || shape==df::tiletype_shape::STAIR_UP)
{
if(ZZ!=window_z)
{
cellArray[block_x][block_y]=lightCell(0,0,0);
}
}
else if(shape==df::tiletype_shape::STAIR_DOWN || shape==df::tiletype_shape::STAIR_UPDOWN)
{
cellArray[block_x][block_y]*=lightCell(0.9,0.9,0.9);
}
if(d.bits.liquid_type == df::enums::tile_liquid::Water && d.bits.flow_size)
{
cellArray[block_x][block_y] *= (lightCell(1,1,1) - (lightCell(1,1,1) - lightCell(0.63f,0.63f,0.75f))*((float)d.bits.flow_size/7.0f));
}
else if(d.bits.liquid_type == df::enums::tile_liquid::Magma && d.bits.flow_size > 3)
{
cellArray[block_x][block_y]=lightCell(0,0,0);
}
if(cellArray[block_x][block_y].r < 0.003f && cellArray[block_x][block_y].g < 0.003f && cellArray[block_x][block_y].b < 0.003f)
totalBlank++;
} }
} }
if(emptyCell==256)
continue;
for(int block_x = 0; block_x < 16; block_x++) for(int block_x = 0; block_x < 16; block_x++)
for(int block_y = 0; block_y < 16; block_y++) for(int block_y = 0; block_y < 16; block_y++)
{ {
lightCell& curCell=cellArray[block_x][block_y];
df::coord2d pos; df::coord2d pos;
pos.x = blockx*16+block_x; pos.x = blockX*16+block_x;
pos.y = blocky*16+block_y; pos.y = blockY*16+block_y;
int wx=pos.x-window_x+vp.first.x; pos=worldToViewportCoord(pos,vp,window2d);
int wy=pos.y-window_y+vp.first.y; if(isInViewport(pos,vp) && curCell.dot(curCell)>0.003f)
if(wx>=vp.first.x && wy>=vp.first.y && wx<=vp.second.x && wy<=vp.second.y)
if(cellArray[block_x][block_y].r >= 0.003f && cellArray[block_x][block_y].g >= 0.003f && cellArray[block_x][block_y].b >= 0.003f)
{ {
lightSource sun=lightSource(cellArray[block_x][block_y],15); lightSource sun=lightSource(curCell,15);
addLight(getIndex(wx,wy),sun); addLight(getIndex(pos.x,pos.y),sun);
} }
} }
} }
for(int x=window_x;x<window_x+vpW;x++) }
for(int y=window_y;y<window_y+vpH;y++) void lightingEngineViewscreen::doOcupancyAndLights()
{
// TODO better curve (+red dawn ?)
float daycol = abs((*df::global::cur_year_tick % 1200) - 600.0) / 400.0;
lightCell sky_col(daycol, daycol, daycol);
lightSource sky(sky_col, 15);
lightSource candle(lightCell(0.96f,0.84f,0.03f),5);
lightSource torch(lightCell(0.9f,0.75f,0.3f),8);
//perfectly blocking material
MapExtras::MapCache cache;
doSun(sky,cache);
int window_x=*df::global::window_x;
int window_y=*df::global::window_y;
coord2d window2d(window_x,window_y);
int window_z=*df::global::window_z;
rect2d vp=getMapViewport();
coord2d vpSize=rect_size(vp);
rect2d blockVp;
blockVp.first=coord2d(window_x,window_y)/16;
blockVp.second=(window2d+vpSize)/16;
blockVp.second.x=std::min(blockVp.second.x,(int16_t)df::global::world->map.x_count_block);
blockVp.second.y=std::min(blockVp.second.y,(int16_t)df::global::world->map.y_count_block);
for(int blockX=blockVp.first.x;blockX<=blockVp.second.x;blockX++)
for(int blockY=blockVp.first.y;blockY<=blockVp.second.y;blockY++)
{ {
int wx=x-window_x+vp.first.x; MapExtras::Block* b=cache.BlockAt(DFCoord(blockX,blockY,window_z));
int wy=y-window_y+vp.first.y; MapExtras::Block* bDown=cache.BlockAt(DFCoord(blockX,blockY,window_z-1));
int tile=getIndex(wx,wy); if(!b)
lightCell& curCell=ocupancy[tile]; continue; //empty blocks fixed by sun propagation
if(matAmbience.isTransparent)
curCell=matAmbience.transparency; for(int block_x = 0; block_x < 16; block_x++)
df::tiletype* type = Maps::getTileType(x,y,window_z); for(int block_y = 0; block_y < 16; block_y++)
if(!type)
{
//unallocated, do sky
addLight(tile,sky);
continue;
}
df::tiletype_shape shape = ENUM_ATTR(tiletype,shape,*type);
df::tile_designation* d=Maps::getTileDesignation(x,y,window_z);
df::tile_designation* d2=Maps::getTileDesignation(x,y,window_z-1);
df::tile_occupancy* o=Maps::getTileOccupancy(x,y,window_z);
df::tiletype_material m=ENUM_ATTR(tiletype,material,*type);
if(!o || !d )
continue;
if(shape==df::tiletype_shape::BROOK_BED || shape==df::tiletype_shape::WALL || shape==df::tiletype_shape::TREE || d->bits.hidden )
{ {
//TODO split into wall ,etc... df::coord2d pos;
if(shape==df::tiletype_shape::WALL && m==df::tiletype_material::FROZEN_LIQUID) pos.x = blockX*16+block_x;
applyMaterial(tile,matIce); pos.y = blockY*16+block_y;
else df::coord2d gpos=pos;
pos=worldToViewportCoord(pos,vp,window2d);
if(!isInViewport(pos,vp))
continue;
int tile=getIndex(pos.x,pos.y);
lightCell& curCell=ocupancy[tile];
curCell=matAmbience.transparency;
df::tiletype type = b->tiletypeAt(gpos);
df::tile_designation d = b->DesignationAt(gpos);
//df::tile_occupancy o = b->OccupancyAt(gpos);
df::tiletype_shape shape = ENUM_ATTR(tiletype,shape,type);
df::tiletype_shape_basic basic_shape = ENUM_ATTR(tiletype_shape, basic_shape, shape);
df::tiletype_material tileMat= ENUM_ATTR(tiletype,material,type);
DFHack::t_matpair mat=b->staticMaterialAt(gpos);
matLightDef* lightDef=getMaterial(mat.mat_type,mat.mat_index);
if(!lightDef || !lightDef->isTransparent)
lightDef=&matWall;
if(shape==df::tiletype_shape::BROOK_BED || d.bits.hidden )
{
curCell=lightCell(0,0,0); curCell=lightCell(0,0,0);
} }
else if(o->bits.building) else if(shape==df::tiletype_shape::WALL)
{ {
// Fixme: don't iterate the list every frame if(tileMat==df::tiletype_material::FROZEN_LIQUID)
size_t count = df::global::world->buildings.all.size(); applyMaterial(tile,matIce);
if (count <= max_list_size) else
applyMaterial(tile,*lightDef);
}
else if(!d.bits.liquid_type && d.bits.flow_size>3 )
{ {
for(size_t i = 0; i < count; i++) applyMaterial(tile,matWater);
}
if(d.bits.liquid_type && d.bits.flow_size>0)
{
applyMaterial(tile,matLava);
}
else if(shape==df::tiletype_shape::EMPTY || shape==df::tiletype_shape::RAMP_TOP
|| shape==df::tiletype_shape::STAIR_DOWN || shape==df::tiletype_shape::STAIR_UPDOWN)
{
if(bDown)
{ {
df::building *bld = df::global::world->buildings.all[i]; df::tile_designation d2=bDown->DesignationAt(gpos);
if(d2.bits.liquid_type && d2.bits.flow_size>0)
if (window_z == bld->z && {
x >= bld->x1 && x <= bld->x2 && applyMaterial(tile,matLava);
y >= bld->y1 && y <= bld->y2) }
{
df::building_type type = bld->getType();
if (type == df::enums::building_type::WindowGlass || type==df::enums::building_type::WindowGem)
{
applyMaterial(tile,bld->mat_type,bld->mat_index);
}
if (type == df::enums::building_type::Table)
{
addLight(tile,candle);
}
if (type==df::enums::building_type::Statue)
{
addLight(tile,torch);
}
if(type==df::enums::building_type::Door)
{
df::building_doorst* door=static_cast<df::building_doorst*>(bld);
if(door->door_flags.bits.closed)
applyMaterial(tile,bld->mat_type,bld->mat_index,1,&matWall);
}
}
} }
} }
} }
else if(!d->bits.liquid_type && d->bits.flow_size>3 ) //flows
{ df::map_block* block=b->getRaw();
curCell*=lightCell(0.7f,0.7f,0.8f);
}
//lights
if((d->bits.liquid_type && d->bits.flow_size>0)||
(
(shape==df::tiletype_shape::EMPTY || shape==df::tiletype_shape::RAMP_TOP || shape==df::tiletype_shape::STAIR_DOWN || shape==df::tiletype_shape::STAIR_UPDOWN )
&& d2 && d2->bits.liquid_type && d2->bits.flow_size>0)
)
{
addLight(tile,matLava.makeSource());
}
if(d->bits.outside && d->bits.flow_size==0)
{
addLight(tile,sky);
}
}
for(int blockx=window_x/16;blockx<=endBlockx;blockx++)
for(int blocky=window_y/16;blocky<=endBlocky;blocky++)
{
df::map_block* block=Maps::getBlock(blockx,blocky,window_z);
if(!block)
continue;
for(int i=0;i<block->flows.size();i++) for(int i=0;i<block->flows.size();i++)
{ {
df::flow_info* f=block->flows[i]; df::flow_info* f=block->flows[i];
if(f && f->density>0 && f->type==df::flow_type::Dragonfire || f->type==df::flow_type::Fire) if(f && f->density>0 && f->type==df::flow_type::Dragonfire || f->type==df::flow_type::Fire)
{ {
df::coord2d pos=f->pos; df::coord2d pos=f->pos;
int wx=pos.x-window_x+vp.first.x; pos=worldToViewportCoord(pos,vp,window2d);
int wy=pos.y-window_y+vp.first.y; int tile=getIndex(pos.x,pos.y);
int tile=getIndex(wx,wy); if(isInViewport(pos,vp))
if(wx>=vp.first.x && wy>=vp.first.y && wx<=vp.second.x && wy<=vp.second.y)
{ {
lightCell fireColor; lightCell fireColor;
if(f->density>60) if(f->density>60)
@ -517,10 +546,9 @@ void lightingEngineViewscreen::doOcupancyAndLights()
df::plant* cPlant=block->plants[i]; df::plant* cPlant=block->plants[i];
df::coord2d pos=cPlant->pos; df::coord2d pos=cPlant->pos;
int wx=pos.x-window_x+vp.first.x; pos=worldToViewportCoord(pos,vp,window2d);
int wy=pos.y-window_y+vp.first.y; int tile=getIndex(pos.x,pos.y);
int tile=getIndex(wx,wy); if(isInViewport(pos,vp))
if(wx>=vp.first.x && wy>=vp.first.y && wx<=vp.second.x && wy<=vp.second.y)
{ {
applyMaterial(tile,cPlant->material,-1); applyMaterial(tile,cPlant->material,-1);
} }
@ -539,12 +567,45 @@ void lightingEngineViewscreen::doOcupancyAndLights()
for (int i=0;i<df::global::world->units.active.size();++i) for (int i=0;i<df::global::world->units.active.size();++i)
{ {
df::unit *u = df::global::world->units.active[i]; df::unit *u = df::global::world->units.active[i];
if (u->pos.z != window_z || coord2d pos=worldToViewportCoord(coord2d(u->pos.x,u->pos.y),vp,window2d);
(u->pos.x < window_x || u->pos.x >= window_x+vpW) || if(u->pos.z==window_z && isInViewport(pos,vp))
(u->pos.y < window_y || u->pos.y >= window_y+vpH))
continue;
if (DFHack::Units::isCitizen(u) && !u->counters.unconscious) if (DFHack::Units::isCitizen(u) && !u->counters.unconscious)
addLight(getIndex(u->pos.x-window_x+1, u->pos.y-window_y+1),citizen); addLight(getIndex(pos.x,pos.y),citizen);
}
//buildings
for(size_t i = 0; i < df::global::world->buildings.all.size(); i++)
{
df::building *bld = df::global::world->buildings.all[i];
if(window_z!=bld->z)
continue;
df::coord2d p1(bld->x1,bld->y1);
df::coord2d p2(bld->x2,bld->y2);
p1=worldToViewportCoord(p1,vp,window2d);
p2=worldToViewportCoord(p1,vp,window2d);
if(isInViewport(p1,vp)||isInViewport(p2,vp))
{
int tile=getIndex(p1.x,p1.y); //TODO multitile buildings. How they would work?
df::building_type type = bld->getType();
if (type == df::enums::building_type::WindowGlass || type==df::enums::building_type::WindowGem)
{
applyMaterial(tile,bld->mat_type,bld->mat_index);
}
if (type == df::enums::building_type::Table)
{
addLight(tile,candle);
}
if (type==df::enums::building_type::Statue)
{
addLight(tile,torch);
}
if(type==df::enums::building_type::Door)
{
df::building_doorst* door=static_cast<df::building_doorst*>(bld);
if(door->door_flags.bits.closed)
applyMaterial(tile,bld->mat_type,bld->mat_index,1,&matWall);
}
}
} }
} }
lightCell lua_parseLightCell(lua_State* L) lightCell lua_parseLightCell(lua_State* L)
@ -566,7 +627,7 @@ lightCell lua_parseLightCell(lua_State* L)
ret.b=lua_tonumber(L,-1); ret.b=lua_tonumber(L,-1);
lua_pop(L,1); lua_pop(L,1);
Lua::GetOutput(L)->print("got cell(%f,%f,%f)\n",ret.r,ret.g,ret.b); //Lua::GetOutput(L)->print("got cell(%f,%f,%f)\n",ret.r,ret.g,ret.b);
return ret; return ret;
} }
matLightDef lua_parseMatDef(lua_State* L) matLightDef lua_parseMatDef(lua_State* L)
@ -643,6 +704,7 @@ int lightingEngineViewscreen::parseSpecial(lua_State* L)
return 0; return 0;
} }
LOAD_SPECIAL(LAVA,matLava); LOAD_SPECIAL(LAVA,matLava);
LOAD_SPECIAL(WATER,matWater);
LOAD_SPECIAL(FROZEN_LIQUID,matIce); LOAD_SPECIAL(FROZEN_LIQUID,matIce);
LOAD_SPECIAL(AMBIENT,matAmbience); LOAD_SPECIAL(AMBIENT,matAmbience);
LOAD_SPECIAL(CURSOR,matCursor); LOAD_SPECIAL(CURSOR,matCursor);
@ -653,9 +715,11 @@ void lightingEngineViewscreen::defaultSettings()
{ {
matAmbience=matLightDef(lightCell(0.85f,0.85f,0.85f)); matAmbience=matLightDef(lightCell(0.85f,0.85f,0.85f));
matLava=matLightDef(lightCell(0.8f,0.2f,0.2f),lightCell(0.8f,0.2f,0.2f),5); matLava=matLightDef(lightCell(0.8f,0.2f,0.2f),lightCell(0.8f,0.2f,0.2f),5);
matWater=matLightDef(lightCell(0.6f,0.6f,0.8f));
matIce=matLightDef(lightCell(0.7f,0.7f,0.9f)); matIce=matLightDef(lightCell(0.7f,0.7f,0.9f));
matCursor=matLightDef(lightCell(0.96f,0.84f,0.03f),11); matCursor=matLightDef(lightCell(0.96f,0.84f,0.03f),11);
matCursor.flicker=true; matCursor.flicker=true;
matWall=matLightDef(lightCell(0,0,0));
} }
void lightingEngineViewscreen::loadSettings() void lightingEngineViewscreen::loadSettings()
{ {

@ -3,6 +3,8 @@
#include "renderer_opengl.hpp" #include "renderer_opengl.hpp"
#include "Types.h" #include "Types.h"
#include <map> #include <map>
#include "modules/MapCache.h"
struct renderer_light : public renderer_wrap { struct renderer_light : public renderer_wrap {
private: private:
void colorizeTile(int x,int y) void colorizeTile(int x,int y)
@ -112,7 +114,7 @@ struct matLightDef
matLightDef(){} matLightDef(){}
matLightDef(lightCell transparency,lightCell emit,int rad):isTransparent(true),isEmiting(true), matLightDef(lightCell transparency,lightCell emit,int rad):isTransparent(true),isEmiting(true),
transparency(transparency),emitColor(emit),radius(rad){} transparency(transparency),emitColor(emit),radius(rad){}
matLightDef(lightCell emit,int rad):isTransparent(false),isEmiting(true),emitColor(emit),radius(rad){} matLightDef(lightCell emit,int rad):isTransparent(false),isEmiting(true),emitColor(emit),radius(rad),transparency(0,0,0){}
matLightDef(lightCell transparency):isTransparent(true),isEmiting(false),transparency(transparency){} matLightDef(lightCell transparency):isTransparent(true),isEmiting(false),transparency(transparency){}
lightSource makeSource(float size=1) const lightSource makeSource(float size=1) const
{ {
@ -133,12 +135,18 @@ public:
void loadSettings(); void loadSettings();
private: private:
void doOcupancyAndLights(); df::coord2d worldToViewportCoord(const df::coord2d& in,const DFHack::rect2d& r,const df::coord2d& window2d) ;
bool isInViewport(const df::coord2d& in,const DFHack::rect2d& r);
void doSun(const lightSource& sky,MapExtras::MapCache& map);
void doOcupancyAndLights();
lightCell propogateSun(MapExtras::Block* b, int x,int y,const lightCell& in,bool lastLevel);
void doRay(lightCell power,int cx,int cy,int tx,int ty); void doRay(lightCell power,int cx,int cy,int tx,int ty);
void doFovs(); void doFovs();
bool lightUpCell(lightCell& power,int dx,int dy,int tx,int ty); bool lightUpCell(lightCell& power,int dx,int dy,int tx,int ty);
bool addLight(int tileId,const lightSource& light); bool addLight(int tileId,const lightSource& light);
matLightDef* getMaterial(int matType,int matIndex);
//apply material to cell //apply material to cell
void applyMaterial(int tileId,const matLightDef& mat,float size=1); void applyMaterial(int tileId,const matLightDef& mat,float size=1);
//try to find and apply material, if failed return false, and if def!=null then apply def. //try to find and apply material, if failed return false, and if def!=null then apply def.
@ -163,6 +171,8 @@ private:
matLightDef matIce; matLightDef matIce;
matLightDef matAmbience; matLightDef matAmbience;
matLightDef matCursor; matLightDef matCursor;
matLightDef matWall;
matLightDef matWater;
//materials //materials
std::map<std::pair<int,int>,matLightDef> matDefs; std::map<std::pair<int,int>,matLightDef> matDefs;

@ -195,19 +195,19 @@ struct lightCell
{ {
} }
lightCell operator-(lightCell cell) lightCell operator-(lightCell cell) const
{ {
return lightCell(r-cell.r,g-cell.g,b-cell.b); return lightCell(r-cell.r,g-cell.g,b-cell.b);
} }
lightCell operator*(float val) lightCell operator*(float val)const
{ {
return lightCell(r*val,g*val,b*val); return lightCell(r*val,g*val,b*val);
} }
lightCell operator/(float val) lightCell operator/(float val) const
{ {
return lightCell(r/val,g/val,b/val); return lightCell(r/val,g/val,b/val);
} }
lightCell operator*(lightCell cell) lightCell operator*(lightCell cell) const
{ {
return lightCell(r*cell.r,g*cell.g,b*cell.b); return lightCell(r*cell.r,g*cell.g,b*cell.b);
} }
@ -216,16 +216,20 @@ struct lightCell
r*=cell.r; r*=cell.r;
g*=cell.g; g*=cell.g;
b*=cell.b; b*=cell.b;
return lightCell(r,g,b); return *this;
} }
lightCell operator+(const lightCell& other) lightCell operator+(const lightCell& other) const
{ {
return lightCell(r+other.r,g+other.g,b+other.b); return lightCell(r+other.r,g+other.g,b+other.b);
} }
bool operator<(const lightCell& other) bool operator<(const lightCell& other) const
{ {
return r<other.r && g<other.g && b<other.b; return r<other.r && g<other.g && b<other.b;
} }
float dot(const lightCell& other) const
{
return r*other.r+g*other.g+b*other.b;
}
}; };
struct renderer_test : public renderer_wrap { struct renderer_test : public renderer_wrap {
private: private: