diff --git a/plugins/rendermax/renderer_light.cpp b/plugins/rendermax/renderer_light.cpp index 7319c6fe5..c6ec459eb 100644 --- a/plugins/rendermax/renderer_light.cpp +++ b/plugins/rendermax/renderer_light.cpp @@ -1,6 +1,7 @@ #include "renderer_light.hpp" #include +#include #include "Types.h" @@ -13,7 +14,9 @@ #include "df/flow_info.h" #include "df/world.h" #include "df/building.h" - +#include "df/building_doorst.h" +#include "df/plant.h" +#include "df/plant_raw.h" using df::global::gps; using namespace DFHack; @@ -54,6 +57,7 @@ rect2d getMapViewport() lightingEngineViewscreen::lightingEngineViewscreen(renderer_light* target):lightingEngine(target) { reinit(); + initRawSpecific(); } void lightingEngineViewscreen::reinit() @@ -65,6 +69,7 @@ void lightingEngineViewscreen::reinit() size_t size=w*h; lightMap.resize(size,lightCell(1,1,1)); ocupancy.resize(size); + lights.resize(size); } void plotCircle(int xm, int ym, int r,std::function setPixel) { @@ -107,18 +112,23 @@ bool lightingEngineViewscreen::lightUpCell(lightCell& power,int dx,int dy,int tx { size_t tile=getIndex(tx,ty); float dsq=dx*dx+dy*dy; + float dt=sqrt(dsq); lightCell& v=ocupancy[tile]; + lightSource& ls=lights[tile]; bool wallhack=false; - bool outsidehack=false; if(v.r+v.g+v.b==0) wallhack=true; - if(v.r<0) - outsidehack=true; - if (dsq>0 && !wallhack && !outsidehack) + + if (dsq>0 && !wallhack) + { + power.r=power.r*(pow(v.r,dt)); + power.g=power.g*(pow(v.g,dt)); + power.b=power.b*(pow(v.b,dt)); + } + if(ls.radius>0 && dsq>0) { - power.r=power.r*(pow(v.r,dsq)); - power.g=power.g*(pow(v.g,dsq)); - power.b=power.b*(pow(v.b,dsq)); + if(power0 && outsidehack) - return false; float pwsq=power.r*power.r+power.g*power.g+power.b*power.b; return pwsq>levelDim*levelDim; } @@ -145,17 +153,32 @@ void lightingEngineViewscreen::doFovs() { mapPort=getMapViewport(); using namespace std::placeholders; - for(size_t i=0;i0) + { + lightCell power=csource.power; + int radius =csource.radius; + if(csource.flicker) + { + float flicker=(rand()/(float)RAND_MAX)/2.0f+0.5f; + radius*=flicker; + power=power*flicker; + } + plotCircle(i,j,radius, + std::bind(&lightingEngineViewscreen::doRay,this,power,i,j,_1,_2)); + } + } } void lightingEngineViewscreen::calculate() { rect2d vp=getMapViewport(); const lightCell dim(levelDim,levelDim,levelDim); lightMap.assign(lightMap.size(),lightCell(1,1,1)); + lights.assign(lights.size(),lightSource()); for(int i=vp.first.x;ilightGrid.size()) { reinit(); + myRenderer->invalidate(); return; } std::swap(lightMap,myRenderer->lightGrid); @@ -180,14 +204,60 @@ void lightingEngineViewscreen::updateWindow() myRenderer->invalidate(); //std::copy(lightMap.begin(),lightMap.end(),myRenderer->lightGrid.begin()); } - +void lightSource::combine(const lightSource& other) +{ + power=blend(power,other.power); + radius=std::max(other.radius,radius);//hack... but who cares +} +bool lightingEngineViewscreen::addLight(int tileId,const lightSource& light) +{ + bool wasLight=lights[tileId].radius>0; + lights[tileId].combine(light); + if(light.flicker) + lights[tileId].flicker=true; + return wasLight; +} +lightCell getStandartColor(int colorId) +{ + return lightCell(df::global::enabler->ccolor[colorId][0]/255.0f, + df::global::enabler->ccolor[colorId][1]/255.0f, + df::global::enabler->ccolor[colorId][2]/255.0f); +} +int getPlantNumber(const std::string& id) +{ + std::vector& vec=df::plant_raw::get_vector(); + for(int i=0;iid==id) + return i; + } + return -1; +} +void addPlant(const std::string& id,std::map& map,const lightSource& v) +{ + int nId=getPlantNumber(id); + if(nId>0) + { + map[nId]=v; + } +} +void lightingEngineViewscreen::initRawSpecific() +{ + addPlant("TOWER_CAP",glowPlants,lightSource(lightCell(0.65,0.65,0.65),6)); + addPlant("MUSHROOM_CUP_DIMPLE",glowPlants,lightSource(lightCell(0.03,0.03,0.5),3)); + addPlant("CAVE MOSS",glowPlants,lightSource(lightCell(0.1,0.1,0.4),2)); + addPlant("MUSHROOM_HELMET_PLUMP",glowPlants,lightSource(lightCell(0.2,0.1,0.6),2)); +} static size_t max_list_size = 100000; // Avoid iterating over huge lists - void lightingEngineViewscreen::doOcupancyAndLights() { - lights.clear(); + lightSource sun(lightCell(1,1,1),15); + lightSource lava(lightCell(0.8f,0.2f,0.2f),5); + lightSource candle(lightCell(0.96f,0.84f,0.03f),5); + lightSource torch(lightCell(0.9f,0.75f,0.3f),8); rect2d vp=getMapViewport(); + int window_x=*df::global::window_x; int window_y=*df::global::window_y; int window_z=*df::global::window_z; @@ -259,8 +329,9 @@ void lightingEngineViewscreen::doOcupancyAndLights() 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={cellArray[block_x][block_y],25,coord2d(wx,wy)}; - lights.push_back(sun); + int tile=getIndex(wx,wy); + lightSource sun(cellArray[block_x][block_y],25); + addLight(tile,sun); } } @@ -270,19 +341,23 @@ void lightingEngineViewscreen::doOcupancyAndLights() { int wx=x-window_x+vp.first.x; int wy=y-window_y+vp.first.y; - lightCell& curCell=ocupancy[getIndex(wx,wy)]; - curCell=lightCell(0.8f,0.8f,0.8f); + int tile=getIndex(wx,wy); + lightCell& curCell=ocupancy[tile]; + curCell=lightCell(0.85f,0.85f,0.85f); df::tiletype* type = Maps::getTileType(x,y,window_z); - if(!type) - continue; + //if(!type) + //{ + // //unallocated, do sky + // addLight(tile,sun); + // 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); if(!o || !d ) continue; - - if(shape==df::tiletype_shape::BROOK_BED || shape==df::tiletype_shape::WALL || shape==df::tiletype_shape::TREE /*|| o->bits.building*/) + if(shape==df::tiletype_shape::BROOK_BED || shape==df::tiletype_shape::WALL || shape==df::tiletype_shape::TREE || d->bits.hidden ) { curCell=lightCell(0,0,0); } @@ -317,33 +392,55 @@ void lightingEngineViewscreen::doOcupancyAndLights() curCell*=lightCell(0.75f,0.95f,0.95f); } } + 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::WindowGem) + { + DFHack::MaterialInfo mat(bld->mat_index,bld->mat_type); + if(mat.isInorganic()) + { + int color=mat.inorganic->material.basic_color[0]+8*mat.inorganic->material.basic_color[2]; + curCell*=getStandartColor(color); + } + } + if(type==df::enums::building_type::Door) + { + df::building_doorst* door=static_cast(bld); + if(door->door_flags.bits.closed) + curCell*=lightCell(0,0,0); + } } } } } else if(!d->bits.liquid_type && d->bits.flow_size>3 ) { - curCell=lightCell(0.5f,0.5f,0.6f); + curCell*=lightCell(0.7f,0.7f,0.8f); } - //todo constructions //lights - if((d->bits.liquid_type && d->bits.flow_size>0)|| (d2 && d2->bits.liquid_type && d2->bits.flow_size>0)) + 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) + ) { - lightSource lava={lightCell(0.8f,0.2f,0.2f),5,coord2d(wx,wy)}; - lights.push_back(lava); + + addLight(tile,lava); } - if(d->bits.outside && d->bits.flow_size==0) - { - curCell=lightCell(-1,-1,-1);//Marking as outside so no calculation is done on it - } - } 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;iflows.size();i++) @@ -354,6 +451,7 @@ void lightingEngineViewscreen::doOcupancyAndLights() df::coord2d pos=f->pos; int wx=pos.x-window_x+vp.first.x; int wy=pos.y-window_y+vp.first.y; + int tile=getIndex(wx,wy); if(wx>=vp.first.x && wy>=vp.first.y && wx<=vp.second.x && wy<=vp.second.y) { lightCell fireColor; @@ -369,10 +467,36 @@ void lightingEngineViewscreen::doOcupancyAndLights() { fireColor=lightCell(0.64f,0.0f,0.0f); } - lightSource fire={fireColor,f->density/5,coord2d(wx,wy)}; - lights.push_back(fire); + lightSource fire(fireColor,f->density/5); + addLight(tile,fire); + } + } + } + for(int i=0;iplants.size();i++) + { + df::plant* cPlant=block->plants[i]; + + df::coord2d pos=cPlant->pos; + int wx=pos.x-window_x+vp.first.x; + int wy=pos.y-window_y+vp.first.y; + int tile=getIndex(wx,wy); + if(wx>=vp.first.x && wy>=vp.first.y && wx<=vp.second.x && wy<=vp.second.y) + { + auto it=glowPlants.find(cPlant->material); + if(it!=glowPlants.end()) + { + addLight(tile,it->second); } } } } + if(df::global::cursor->x>-30000) + { + lightSource cursor(lightCell(0.96f,0.84f,0.03f),11); + cursor.flicker=true; + int wx=df::global::cursor->x-window_x+vp.first.x; + int wy=df::global::cursor->y-window_y+vp.first.y; + int tile=getIndex(wx,wy); + addLight(tile,cursor); + } } \ No newline at end of file diff --git a/plugins/rendermax/renderer_light.hpp b/plugins/rendermax/renderer_light.hpp index d0279fd02..3744fd5bc 100644 --- a/plugins/rendermax/renderer_light.hpp +++ b/plugins/rendermax/renderer_light.hpp @@ -2,7 +2,7 @@ #define RENDERER_LIGHT_INCLUDED #include "renderer_opengl.hpp" #include "Types.h" - +#include struct renderer_light : public renderer_wrap { private: void colorizeTile(int x,int y) @@ -59,7 +59,7 @@ public: }; virtual void resize(int32_t w, int32_t h) { renderer_wrap::resize(w,h); - reinitLightGrid(w,h); + reinitLightGrid(); } }; class lightingEngine @@ -79,7 +79,21 @@ struct lightSource { lightCell power; int radius; - df::coord2d pos; + bool flicker; + lightSource():power(0,0,0),radius(0),flicker(false) + { + + } + lightSource(lightCell power,int radius):power(power),radius(radius),flicker(false) + { + + } + float powerSquared()const + { + return power.r*power.r+power.g*power.g+power.b*power.b; + } + void combine(const lightSource& other); + }; class lightingEngineViewscreen:public lightingEngine { @@ -96,6 +110,8 @@ private: void doRay(lightCell power,int cx,int cy,int tx,int ty); void doFovs(); bool lightUpCell(lightCell& power,int dx,int dy,int tx,int ty); + bool addLight(int tileId,const lightSource& light); + void initRawSpecific(); size_t inline getIndex(int x,int y) { return x*h+y; @@ -103,6 +119,11 @@ private: std::vector lightMap; std::vector ocupancy; std::vector lights; + + + std::map glowPlants; + std::map glowVeins; + int w,h; DFHack::rect2d mapPort; }; diff --git a/plugins/rendermax/renderer_opengl.hpp b/plugins/rendermax/renderer_opengl.hpp index aa14a8c70..6d21a8b4c 100644 --- a/plugins/rendermax/renderer_opengl.hpp +++ b/plugins/rendermax/renderer_opengl.hpp @@ -222,6 +222,10 @@ struct lightCell { return lightCell(r+other.r,g+other.g,b+other.b); } + bool operator<(const lightCell& other) + { + return rrenderer; current_mode=MODE_DEFAULT; - if(current_mode==MODE_LIGHT) - { - if(engine) - delete engine; - engine=0; - } } void installNew(df::renderer* r,RENDERER_MODE newMode) { @@ -241,6 +235,11 @@ static command_result rendermax(color_ostream &out, vector & parameters { if(parameters.size()==0) return CR_WRONG_USAGE; + if(!df::global::enabler->renderer->uses_opengl()) + { + out.printerr("Sorry, this plugin needs open gl enabled printmode. Try STANDARD or other non-2d"); + return CR_FAILURE; + } string cmd=parameters[0]; if(cmd=="trippy") { @@ -305,26 +304,20 @@ static command_result rendermax(color_ostream &out, vector & parameters } else if(cmd=="light") { - if(current_mode==MODE_LIGHT) - { - engine->calculate(); - engine->updateWindow(); - } - else - { - removeOld(); - renderer_light *myRender=new renderer_light(df::global::enabler->renderer); - installNew(myRender,MODE_LIGHT); - engine=new lightingEngineViewscreen(myRender); - engine->calculate(); - engine->updateWindow(); - } + removeOld(); + renderer_light *myRender=new renderer_light(df::global::enabler->renderer); + installNew(myRender,MODE_LIGHT); + engine=new lightingEngineViewscreen(myRender); + engine->calculate(); + engine->updateWindow(); return CR_OK; } else if(cmd=="disable") { if(current_mode==MODE_DEFAULT) out.print("%s\n","Not installed, doing nothing."); + else if(current_mode==MODE_LIGHT) + current_mode=MODE_LIGHT_OFF; else removeOld(); @@ -336,9 +329,19 @@ DFhackCExport command_result plugin_onupdate (color_ostream &out) { if(engine) { - engine->calculate(); - engine->updateWindow(); + if(current_mode==MODE_LIGHT_OFF) + { + delete engine; + engine=0; + removeOld(); + } + else + { + engine->calculate(); + engine->updateWindow(); + } } + return CR_OK; } DFhackCExport command_result plugin_shutdown(color_ostream &)