develop
Japa 2013-06-26 19:14:55 +05:30
commit dc42fa2fa3
3 changed files with 232 additions and 27 deletions

@ -432,6 +432,14 @@ matLightDef* lightingEngineViewscreen::getMaterial(int matType,int matIndex)
else
return NULL;
}
buildingLightDef* lightingEngineViewscreen::getBuilding(df::building* bld)
{
auto it=buildingDefs.find(std::make_tuple((int)bld->getType(),(int)bld->getSubtype(),(int)bld->getCustomType()));
if(it!=buildingDefs.end())
return &it->second;
else
return NULL;
}
void lightingEngineViewscreen::applyMaterial(int tileId,const matLightDef& mat,float size, float thickness)
{
if(mat.isTransparent)
@ -465,7 +473,7 @@ lightCell lightingEngineViewscreen::propogateSun(MapExtras::Block* b, int x,int
const lightCell matStairCase(0.9f,0.9f,0.9f);
lightCell ret=in;
coord2d innerCoord(x,y);
df::tiletype type = b->tiletypeAt(innerCoord);
df::tiletype type = b->staticTiletypeAt(innerCoord);
df::tile_designation d = b->DesignationAt(innerCoord);
//df::tile_occupancy o = b->OccupancyAt(innerCoord);
df::tiletype_shape shape = ENUM_ATTR(tiletype,shape,type);
@ -475,8 +483,17 @@ lightCell lightingEngineViewscreen::propogateSun(MapExtras::Block* b, int x,int
matLightDef* lightDef;
if(tileMat==df::tiletype_material::FROZEN_LIQUID)
lightDef=&matIce;
else
{
df::tiletype typeIce = b->tiletypeAt(innerCoord);
df::tiletype_shape shapeIce = ENUM_ATTR(tiletype,shape,typeIce);
df::tiletype_shape_basic basicShapeIce = ENUM_ATTR(tiletype_shape,basic_shape,shapeIce);
if(basicShapeIce==df::tiletype_shape_basic::Wall)
ret*=matIce.transparency;
else if(basicShapeIce==df::tiletype_shape_basic::Floor || basicShapeIce==df::tiletype_shape_basic::Ramp || shapeIce==df::tiletype_shape::STAIR_UP)
if(!lastLevel)
ret*=matIce.transparency.power(1.0f/7.0f);
}
lightDef=getMaterial(mat.mat_type,mat.mat_index);
if(!lightDef || !lightDef->isTransparent)
@ -487,6 +504,7 @@ lightCell lightingEngineViewscreen::propogateSun(MapExtras::Block* b, int x,int
}
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.power(1.0f/7.0f);
}
@ -624,6 +642,11 @@ void lightingEngineViewscreen::doOcupancyAndLights()
df::tiletype type = b->tiletypeAt(gpos);
df::tile_designation d = b->DesignationAt(gpos);
if(d.bits.hidden)
{
curCell=lightCell(0,0,0);
continue; // do not process hidden stuff
}
//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);
@ -634,7 +657,7 @@ void lightingEngineViewscreen::doOcupancyAndLights()
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 )
if(shape==df::tiletype_shape::BROOK_BED )
{
curCell=lightCell(0,0,0);
}
@ -665,6 +688,8 @@ void lightingEngineViewscreen::doOcupancyAndLights()
}
}
}
}
df::map_block* block=b->getRaw();
@ -712,6 +737,36 @@ void lightingEngineViewscreen::doOcupancyAndLights()
applyMaterial(tile,419,cPlant->material);
}
}
//blood and other goo
for(int i=0;i<block->block_events.size();i++)
{
df::block_square_event* ev=block->block_events[i];
df::block_square_event_type ev_type=ev->getType();
if(ev_type==df::block_square_event_type::material_spatter)
{
df::block_square_event_material_spatterst* spatter=static_cast<df::block_square_event_material_spatterst*>(ev);
matLightDef* m=getMaterial(spatter->mat_type,spatter->mat_index);
if(!m)
continue;
if(!m->isEmiting)
continue;
for(int x=0;x<16;x++)
for(int y=0;y<16;y++)
{
df::coord2d pos;
pos.x = blockX*16+x;
pos.y = blockY*16+y;
int16_t amount=spatter->amount[x][y];
if(amount<=0)
continue;
pos=worldToViewportCoord(pos,vp,window2d);
if(isInViewport(pos,vp))
{
addLight(getIndex(pos.x,pos.y),m->makeSource((float)amount/100));
}
}
}
}
}
if(df::global::cursor->x>-30000)
{
@ -734,38 +789,63 @@ void lightingEngineViewscreen::doOcupancyAndLights()
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;
if(bld->getBuildStage()<bld->getMaxBuildStage()) //only work if fully built
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();
buildingLightDef* def=getBuilding(bld);
if(!def)
continue;
if(def->poweredOnly && bld->isUnpowered())
continue;
if(type==df::enums::building_type::Door)
{
df::building_doorst* door=static_cast<df::building_doorst*>(bld);
if(!door->door_flags.bits.closed)
continue;
}
if (type == df::enums::building_type::WindowGlass || type==df::enums::building_type::WindowGem)
if(def->useMaterial)
{
applyMaterial(tile,bld->mat_type,bld->mat_index);
matLightDef* mat=getMaterial(bld->mat_type,bld->mat_index);
if(!mat)mat=&matWall;
if(def->light.isEmiting)
{
addLight(tile,def->light.makeSource());
}
if (type == df::enums::building_type::Table)
else if(mat->isEmiting)
{
addLight(tile,candle);
addLight(tile,mat->makeSource());
}
if (type==df::enums::building_type::Statue)
if(def->light.isTransparent)
{
addLight(tile,torch);
ocupancy[tile]*=def->light.transparency;
}
if(type==df::enums::building_type::Door)
else
{
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);
ocupancy[tile]*=mat->transparency;
}
}
else
{
applyMaterial(tile,def->light);
}
}
}
}
lightCell lua_parseLightCell(lua_State* L)
{
lightCell ret;
@ -788,6 +868,10 @@ lightCell lua_parseLightCell(lua_State* L)
//Lua::GetOutput(L)->print("got cell(%f,%f,%f)\n",ret.r,ret.g,ret.b);
return ret;
}
#define GETLUAFLAG(field,name) lua_getfield(L,-1,"flags");\
if(lua_isnil(L,-1)){field=false;}\
else{lua_getfield(L,-1,#name);field=lua_isnil(L,-1);lua_pop(L,1);}\
lua_pop(L,1)
matLightDef lua_parseMatDef(lua_State* L)
{
@ -816,7 +900,10 @@ matLightDef lua_parseMatDef(lua_State* L)
}
else
lua_pop(L,1);
//todo flags
GETLUAFLAG(ret.flicker,"flicker");
GETLUAFLAG(ret.useThickness,"useThickness");
GETLUAFLAG(ret.sizeModifiesPower,"sizeModifiesPower");
GETLUAFLAG(ret.sizeModifiesRange,"sizeModifiesRange");
return ret;
}
int lightingEngineViewscreen::parseMaterials(lua_State* L)
@ -873,6 +960,48 @@ int lightingEngineViewscreen::parseSpecial(lua_State* L)
return 0;
}
#undef LOAD_SPECIAL
int lightingEngineViewscreen::parseBuildings(lua_State* L)
{
auto engine= (lightingEngineViewscreen*)lua_touserdata(L, 1);
engine->buildingDefs.clear();
Lua::StackUnwinder unwinder(L);
lua_getfield(L,2,"buildings");
if(!lua_istable(L,-1))
{
luaL_error(L,"Buildings table not found.");
return 0;
}
lua_pushnil(L);
while (lua_next(L, -2) != 0) {
int type=lua_tonumber(L,-2);
if(!lua_istable(L,-1))
{
luaL_error(L,"Broken building definitions.");
}
//os->print("Processing type:%d\n",type);
lua_pushnil(L);
while (lua_next(L, -2) != 0) {
int subtype=lua_tonumber(L,-2);
//os->print("\tProcessing subtype:%d\n",index);
lua_pushnil(L);
while (lua_next(L, -2) != 0) {
int custom=lua_tonumber(L,-2);
//os->print("\tProcessing custom:%d\n",index);
buildingLightDef current;
current.light=lua_parseMatDef(L);
engine->buildingDefs[std::make_tuple(type,subtype,custom)]=current;
GETLUAFLAG(current.poweredOnly,"poweredOnly");
GETLUAFLAG(current.useMaterial,"useMaterial");
lua_pop(L, 1);
}
lua_pop(L, 1);
}
lua_pop(L, 1);
}
lua_pop(L,1);
return 0;
}
void lightingEngineViewscreen::defaultSettings()
{
matAmbience=matLightDef(lightCell(0.85f,0.85f,0.85f));
@ -923,6 +1052,11 @@ void lightingEngineViewscreen::loadSettings()
lua_pushvalue(s,env);
Lua::SafeCall(out,s,2,0);
lua_pushcfunction(s, parseBuildings);
lua_pushlightuserdata(s, this);
lua_pushvalue(s,env);
Lua::SafeCall(out,s,2,0);
out.print("%d buildings loaded\n",buildingDefs.size());
}
}
@ -933,3 +1067,4 @@ void lightingEngineViewscreen::loadSettings()
}
lua_pop(s,1);
}
#undef GETLUAFLAG

@ -3,6 +3,7 @@
#include "renderer_opengl.hpp"
#include "Types.h"
#include <map>
#include <tuple>
#include "modules/MapCache.h"
struct renderer_light : public renderer_wrap {
@ -99,11 +100,10 @@ struct lightSource
};
struct matLightDef
{
int mat_index;
int mat_type;
bool isTransparent;
lightCell transparency;
bool isEmiting;
bool useThickness;
bool sizeModifiesPower;
bool sizeModifiesRange;
bool flicker;
@ -120,6 +120,12 @@ struct matLightDef
return lightSource(emitColor,radius);
}
};
struct buildingLightDef
{
matLightDef light;
bool poweredOnly;
bool useMaterial;
};
class lightingEngineViewscreen:public lightingEngine
{
public:
@ -147,10 +153,13 @@ private:
bool addLight(int tileId,const lightSource& light);
matLightDef* getMaterial(int matType,int matIndex);
buildingLightDef* getBuilding(df::building* bld);
//apply material to cell
void applyMaterial(int tileId,const matLightDef& mat,float size=1, float thickness = 1);
//try to find and apply material, if failed return false, and if def!=null then apply def.
bool applyMaterial(int tileId,int matType,int matIndex,float size=1,const matLightDef* def=NULL);
size_t inline getIndex(int x,int y)
{
return x*h+y;
@ -181,6 +190,7 @@ private:
static int parseMaterials(lua_State* L);
static int parseSpecial(lua_State* L);
static int parseBuildings(lua_State* L);
//special stuff
matLightDef matLava;
matLightDef matIce;
@ -192,7 +202,8 @@ private:
float levelDim;
//materials
std::map<std::pair<int,int>,matLightDef> matDefs;
//buildings
std::map<std::tuple<int,int,int>,buildingLightDef> buildingDefs;
int w,h;
DFHack::rect2d mapPort;
};

@ -8,8 +8,9 @@ for k,v in pairs(ret) do
_ENV[k]=v
end
-- add material by id (index,mat pair or token string or a type number), flags is a table of strings
-- supported flags:
-- supported flags (but not implemented):
-- flicker
-- useThickness -- use thickness of stuff in transparency calculation
-- sizeModifiesPower
-- sizeModifiesRange
function addMaterial(id,transparency,emitance,radius,flags)
@ -27,8 +28,58 @@ function addMaterial(id,transparency,emitance,radius,flags)
materials[matinfo.type]=materials[matinfo.type] or {}
materials[matinfo.type][matinfo.index]=makeMaterialDef(transparency,emitance,radius,flags)
end
function buildingLookUp(id)
local tokens={}
local lookup={ Workshop=df.workshop_type,Furnace=df.furnace_type,Trap=df.trap_type,
SiegeEngine=siegeengine_type}
for i in string.gmatch(id, "[^:]+") do
table.insert(tokens,i)
end
local ret={}
ret.type=df.building_type[tokens[1]]
if tokens[2] then
local type_array=lookup[tokens[1]]
if type_array then
ret.subtype=type_array[tokens[2]]
end
if tokens[2]=="Custom" and tokens[3] then --TODO cache for faster lookup
if ret.type==df.building_type.Workshop then
for k,v in pairs(df.global.world.raws.buildings.workshops) do
if v.code==tokens[3] then
ret.custom=v.id
break
end
end
elseif ret.type==df.building_type.Furnace then
for k,v in pairs(df.global.world.raws.buildings.furnaces) do
if v.code==tokens[3] then
ret.custom=v.id
break
end
end
end
end
end
return ret
end
-- add building by id (string e.g. "Statue" or "Workshop:Masons", flags is a table of strings
-- supported flags:
-- useMaterial --uses material, but the defined things overwrite
-- poweredOnly --glow only when powered
function addBuilding(id,transparency,emitance,radius,flags)
--stuff
local bld=buildingLookUp(id)
local mat=makeMaterialDef(transparency,emitance,radius,flags)
buildings[bld.type]=buildings[bld.type] or {}
if bld.subtype then
if bld.custom then
buildings[bld.type][bld.subtype]=buildings[bld.type][bld.subtype] or {}
buildings[bld.type][bld.subtype][bld.custom]=mat
else
buildings[bld.type][bld.subtype]={[-1]=mat}
end
else
buildings[bld.type][-1]={[-1]=mat}
end
end
function makeMaterialDef(transparency,emitance,radius,flags)
local flg
@ -43,6 +94,7 @@ end
------------------------------------------------------------------------
---------------- Configuration Starts Here -------------------------
------------------------------------------------------------------------
is_computer_quantum=false -- will enable more costly parts in the future
--special things
special.LAVA=makeMaterialDef({0.8,0.2,0.2},{0.8,0.2,0.2},5)
special.WATER=makeMaterialDef({0.5,0.5,0.8})
@ -67,5 +119,12 @@ addMaterial("PLANT:CAVE MOSS",nil,{0.1,0.1,0.4},2)
addMaterial("PLANT:MUSHROOM_HELMET_PLUMP",nil,{0.2,0.1,0.6},2)
-- inorganics
addMaterial("INORGANIC:ADAMANTINE",{0.1,0.3,0.3},{0.1,0.3,0.3},4)
-- creature stuff
addMaterial("CREATURE:DRAGON:BLOOD",nil,{0.6,0.1,0.1},4)
-- TODO gems
--buildings
addBuilding("Statue",{1,1,1},{0.9,0.75,0.3},8)
addBuilding("Bed",{1,1,1},{0.3,0.2,0.0},2)
addBuilding("WindowGlass",nil,nil,0,{"useMaterial"})
addBuilding("WindowGem",nil,nil,0,{"useMaterial"})
addBuilding("Door",nil,nil,0,{"useMaterial"}) -- special case, only closed door obstruct/emit light