From 1d2accbe94302f7f9d75f970e08df85443391c66 Mon Sep 17 00:00:00 2001 From: Warmist Date: Tue, 25 Jun 2013 22:49:52 +0300 Subject: [PATCH 1/2] fixed (?) ice and made dragon blood glow a little. --- plugins/rendermax/renderer_light.cpp | 55 +++++++++++++++++++++++++--- plugins/rendermax/rendermax.lua | 2 + 2 files changed, 51 insertions(+), 6 deletions(-) diff --git a/plugins/rendermax/renderer_light.cpp b/plugins/rendermax/renderer_light.cpp index 9e03ca9aa..f1705cfd9 100644 --- a/plugins/rendermax/renderer_light.cpp +++ b/plugins/rendermax/renderer_light.cpp @@ -332,7 +332,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); @@ -342,9 +342,18 @@ lightCell lightingEngineViewscreen::propogateSun(MapExtras::Block* b, int x,int matLightDef* lightDef; if(tileMat==df::tiletype_material::FROZEN_LIQUID) - lightDef=&matIce; - else - lightDef=getMaterial(mat.mat_type,mat.mat_index); + { + 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) lightDef=&matWall; @@ -354,6 +363,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); } @@ -495,9 +505,9 @@ void lightingEngineViewscreen::doOcupancyAndLights() 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; @@ -532,6 +542,8 @@ void lightingEngineViewscreen::doOcupancyAndLights() } } } + + } df::map_block* block=b->getRaw(); @@ -579,6 +591,36 @@ void lightingEngineViewscreen::doOcupancyAndLights() applyMaterial(tile,419,cPlant->material); } } + //blood and other goo + for(int i=0;iblock_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(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) { @@ -632,6 +674,7 @@ void lightingEngineViewscreen::doOcupancyAndLights() } } } + } lightCell lua_parseLightCell(lua_State* L) { diff --git a/plugins/rendermax/rendermax.lua b/plugins/rendermax/rendermax.lua index 4b19e2485..4e335ec86 100644 --- a/plugins/rendermax/rendermax.lua +++ b/plugins/rendermax/rendermax.lua @@ -67,5 +67,7 @@ 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 From fbbae3e9008b28da109dee97575bec902f574ce6 Mon Sep 17 00:00:00 2001 From: Warmist Date: Wed, 26 Jun 2013 01:18:26 +0300 Subject: [PATCH 2/2] Implemented building support. --- plugins/rendermax/renderer_light.cpp | 124 +++++++++++++++++++++++---- plugins/rendermax/renderer_light.hpp | 17 +++- plugins/rendermax/rendermax.lua | 61 ++++++++++++- 3 files changed, 181 insertions(+), 21 deletions(-) diff --git a/plugins/rendermax/renderer_light.cpp b/plugins/rendermax/renderer_light.cpp index f1705cfd9..1cdc1cf4b 100644 --- a/plugins/rendermax/renderer_light.cpp +++ b/plugins/rendermax/renderer_light.cpp @@ -299,6 +299,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) @@ -501,6 +509,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); @@ -511,7 +524,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); } @@ -643,34 +656,58 @@ 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()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(); - - 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) + buildingLightDef* def=getBuilding(bld); + if(!def) + continue; + if(def->poweredOnly && bld->isUnpowered()) + continue; + if(type==df::enums::building_type::Door) { - addLight(tile,candle); + df::building_doorst* door=static_cast(bld); + if(!door->door_flags.bits.closed) + continue; } - if (type==df::enums::building_type::Statue) + + + if(def->useMaterial) { - addLight(tile,torch); + matLightDef* mat=getMaterial(bld->mat_type,bld->mat_index); + if(!mat)mat=&matWall; + if(def->light.isEmiting) + { + addLight(tile,def->light.makeSource()); + } + else if(mat->isEmiting) + { + addLight(tile,mat->makeSource()); + } + if(def->light.isTransparent) + { + ocupancy[tile]*=def->light.transparency; + } + else + { + ocupancy[tile]*=mat->transparency; + } } - if(type==df::enums::building_type::Door) + else { - df::building_doorst* door=static_cast(bld); - if(door->door_flags.bits.closed) - applyMaterial(tile,bld->mat_type,bld->mat_index,1,&matWall); + applyMaterial(tile,def->light); } } } @@ -698,6 +735,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) { @@ -726,7 +767,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) @@ -783,6 +827,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)); @@ -832,7 +918,12 @@ void lightingEngineViewscreen::loadSettings() lua_pushlightuserdata(s, this); 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()); } } @@ -843,3 +934,4 @@ void lightingEngineViewscreen::loadSettings() } lua_pop(s,1); } +#undef GETLUAFLAG \ No newline at end of file diff --git a/plugins/rendermax/renderer_light.hpp b/plugins/rendermax/renderer_light.hpp index a80d314d4..176203cb1 100644 --- a/plugins/rendermax/renderer_light.hpp +++ b/plugins/rendermax/renderer_light.hpp @@ -3,6 +3,7 @@ #include "renderer_opengl.hpp" #include "Types.h" #include +#include #include "modules/MapCache.h" struct renderer_light : public renderer_wrap { @@ -102,11 +103,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; @@ -123,6 +123,12 @@ struct matLightDef return lightSource(emitColor,radius); } }; +struct buildingLightDef +{ + matLightDef light; + bool poweredOnly; + bool useMaterial; +}; class lightingEngineViewscreen:public lightingEngine { public: @@ -149,10 +155,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; @@ -168,6 +177,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; @@ -179,7 +189,8 @@ private: float levelDim; //materials std::map,matLightDef> matDefs; - + //buildings + std::map,buildingLightDef> buildingDefs; int w,h; DFHack::rect2d mapPort; }; diff --git a/plugins/rendermax/rendermax.lua b/plugins/rendermax/rendermax.lua index 4e335ec86..785cb8b1d 100644 --- a/plugins/rendermax/rendermax.lua +++ b/plugins/rendermax/rendermax.lua @@ -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}) @@ -71,3 +123,8 @@ addMaterial("INORGANIC:ADAMANTINE",{0.1,0.3,0.3},{0.1,0.3,0.3},4) 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 \ No newline at end of file