Conflicts:
	plugins/rendermax/renderer_light.cpp
Still broken. Needs boundary checking.
develop
Japa 2013-06-24 03:11:46 +05:30
commit fe41504952
4 changed files with 216 additions and 64 deletions

@ -1,6 +1,7 @@
#include "renderer_light.hpp" #include "renderer_light.hpp"
#include <functional> #include <functional>
#include <string>
#include "Types.h" #include "Types.h"
@ -13,7 +14,9 @@
#include "df/flow_info.h" #include "df/flow_info.h"
#include "df/world.h" #include "df/world.h"
#include "df/building.h" #include "df/building.h"
#include "df/building_doorst.h"
#include "df/plant.h"
#include "df/plant_raw.h"
using df::global::gps; using df::global::gps;
using namespace DFHack; using namespace DFHack;
@ -54,6 +57,7 @@ rect2d getMapViewport()
lightingEngineViewscreen::lightingEngineViewscreen(renderer_light* target):lightingEngine(target) lightingEngineViewscreen::lightingEngineViewscreen(renderer_light* target):lightingEngine(target)
{ {
reinit(); reinit();
initRawSpecific();
} }
void lightingEngineViewscreen::reinit() void lightingEngineViewscreen::reinit()
@ -65,6 +69,7 @@ void lightingEngineViewscreen::reinit()
size_t size=w*h; size_t size=w*h;
lightMap.resize(size,lightCell(1,1,1)); lightMap.resize(size,lightCell(1,1,1));
ocupancy.resize(size); ocupancy.resize(size);
lights.resize(size);
} }
void plotCircle(int xm, int ym, int r,std::function<void(int,int)> setPixel) void plotCircle(int xm, int ym, int r,std::function<void(int,int)> setPixel)
{ {
@ -107,18 +112,23 @@ bool lightingEngineViewscreen::lightUpCell(lightCell& power,int dx,int dy,int tx
{ {
size_t tile=getIndex(tx,ty); size_t tile=getIndex(tx,ty);
float dsq=dx*dx+dy*dy; float dsq=dx*dx+dy*dy;
float dt=sqrt(dsq);
lightCell& v=ocupancy[tile]; lightCell& v=ocupancy[tile];
lightSource& ls=lights[tile];
bool wallhack=false; bool wallhack=false;
bool outsidehack=false;
if(v.r+v.g+v.b==0) if(v.r+v.g+v.b==0)
wallhack=true; wallhack=true;
if(v.r<0)
outsidehack=true; if (dsq>0 && !wallhack)
if (dsq>0 && !wallhack && !outsidehack) {
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)); if(power<ls.power)
power.g=power.g*(pow(v.g,dsq)); return false;
power.b=power.b*(pow(v.b,dsq));
} }
//float dt=sqrt(dsq); //float dt=sqrt(dsq);
lightCell oldCol=lightMap[tile]; lightCell oldCol=lightMap[tile];
@ -127,8 +137,6 @@ bool lightingEngineViewscreen::lightUpCell(lightCell& power,int dx,int dy,int tx
if(wallhack) if(wallhack)
return false; return false;
if(dsq>0 && outsidehack)
return false;
float pwsq=power.r*power.r+power.g*power.g+power.b*power.b; float pwsq=power.r*power.r+power.g*power.g+power.b*power.b;
return pwsq>levelDim*levelDim; return pwsq>levelDim*levelDim;
} }
@ -145,17 +153,32 @@ void lightingEngineViewscreen::doFovs()
{ {
mapPort=getMapViewport(); mapPort=getMapViewport();
using namespace std::placeholders; using namespace std::placeholders;
for(size_t i=0;i<lights.size();i++)
{ for(int i=mapPort.first.x;i<mapPort.second.x;i++)
lightSource& csource=lights[i]; for(int j=mapPort.first.y;j<mapPort.second.y;j++)
plotCircle(csource.pos.x,csource.pos.y,csource.radius,std::bind(&lightingEngineViewscreen::doRay,this,csource.power,csource.pos.x,csource.pos.y,_1,_2)); {
} lightSource& csource=lights[getIndex(i,j)];
if(csource.radius>0)
{
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() void lightingEngineViewscreen::calculate()
{ {
rect2d vp=getMapViewport(); rect2d vp=getMapViewport();
const lightCell dim(levelDim,levelDim,levelDim); const lightCell dim(levelDim,levelDim,levelDim);
lightMap.assign(lightMap.size(),lightCell(1,1,1)); lightMap.assign(lightMap.size(),lightCell(1,1,1));
lights.assign(lights.size(),lightSource());
for(int i=vp.first.x;i<vp.second.x;i++) for(int i=vp.first.x;i<vp.second.x;i++)
for(int j=vp.first.y;j<vp.second.y;j++) for(int j=vp.first.y;j<vp.second.y;j++)
{ {
@ -171,6 +194,7 @@ void lightingEngineViewscreen::updateWindow()
if(lightMap.size()!=myRenderer->lightGrid.size()) if(lightMap.size()!=myRenderer->lightGrid.size())
{ {
reinit(); reinit();
myRenderer->invalidate();
return; return;
} }
std::swap(lightMap,myRenderer->lightGrid); std::swap(lightMap,myRenderer->lightGrid);
@ -180,14 +204,60 @@ void lightingEngineViewscreen::updateWindow()
myRenderer->invalidate(); myRenderer->invalidate();
//std::copy(lightMap.begin(),lightMap.end(),myRenderer->lightGrid.begin()); //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<df::plant_raw*>& vec=df::plant_raw::get_vector();
for(int i=0;i<vec.size();i++)
{
if(vec[i]->id==id)
return i;
}
return -1;
}
void addPlant(const std::string& id,std::map<int,lightSource>& 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 static size_t max_list_size = 100000; // Avoid iterating over huge lists
void lightingEngineViewscreen::doOcupancyAndLights() 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(); rect2d vp=getMapViewport();
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;
int window_z=*df::global::window_z; 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) 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)}; int tile=getIndex(wx,wy);
lights.push_back(sun); 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 wx=x-window_x+vp.first.x;
int wy=y-window_y+vp.first.y; int wy=y-window_y+vp.first.y;
lightCell& curCell=ocupancy[getIndex(wx,wy)]; int tile=getIndex(wx,wy);
curCell=lightCell(0.8f,0.8f,0.8f); lightCell& curCell=ocupancy[tile];
curCell=lightCell(0.85f,0.85f,0.85f);
df::tiletype* type = Maps::getTileType(x,y,window_z); df::tiletype* type = Maps::getTileType(x,y,window_z);
if(!type) //if(!type)
continue; //{
// //unallocated, do sky
// addLight(tile,sun);
// continue;
//}
df::tiletype_shape shape = ENUM_ATTR(tiletype,shape,*type); df::tiletype_shape shape = ENUM_ATTR(tiletype,shape,*type);
df::tile_designation* d=Maps::getTileDesignation(x,y,window_z); df::tile_designation* d=Maps::getTileDesignation(x,y,window_z);
df::tile_designation* d2=Maps::getTileDesignation(x,y,window_z-1); df::tile_designation* d2=Maps::getTileDesignation(x,y,window_z-1);
df::tile_occupancy* o=Maps::getTileOccupancy(x,y,window_z); df::tile_occupancy* o=Maps::getTileOccupancy(x,y,window_z);
if(!o || !d ) if(!o || !d )
continue; continue;
if(shape==df::tiletype_shape::BROOK_BED || shape==df::tiletype_shape::WALL || shape==df::tiletype_shape::TREE || d->bits.hidden )
if(shape==df::tiletype_shape::BROOK_BED || shape==df::tiletype_shape::WALL || shape==df::tiletype_shape::TREE /*|| o->bits.building*/)
{ {
curCell=lightCell(0,0,0); curCell=lightCell(0,0,0);
} }
@ -317,33 +392,55 @@ void lightingEngineViewscreen::doOcupancyAndLights()
curCell*=lightCell(0.75f,0.95f,0.95f); 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<df::building_doorst*>(bld);
if(door->door_flags.bits.closed)
curCell*=lightCell(0,0,0);
}
} }
} }
} }
} }
else if(!d->bits.liquid_type && d->bits.flow_size>3 ) 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 //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 blockx=window_x/16;blockx<=endBlockx;blockx++)
for(int blocky=window_y/16;blocky<=endBlocky;blocky++) for(int blocky=window_y/16;blocky<=endBlocky;blocky++)
{ {
df::map_block* block=Maps::getBlock(blockx,blocky,window_z); df::map_block* block=Maps::getBlock(blockx,blocky,window_z);
if(!block) if(!block)
continue; continue;
for(int i=0;i<block->flows.size();i++) for(int i=0;i<block->flows.size();i++)
@ -354,6 +451,7 @@ void lightingEngineViewscreen::doOcupancyAndLights()
df::coord2d pos=f->pos; df::coord2d pos=f->pos;
int wx=pos.x-window_x+vp.first.x; int wx=pos.x-window_x+vp.first.x;
int wy=pos.y-window_y+vp.first.y; 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) if(wx>=vp.first.x && wy>=vp.first.y && wx<=vp.second.x && wy<=vp.second.y)
{ {
lightCell fireColor; lightCell fireColor;
@ -369,10 +467,36 @@ void lightingEngineViewscreen::doOcupancyAndLights()
{ {
fireColor=lightCell(0.64f,0.0f,0.0f); fireColor=lightCell(0.64f,0.0f,0.0f);
} }
lightSource fire={fireColor,f->density/5,coord2d(wx,wy)}; lightSource fire(fireColor,f->density/5);
lights.push_back(fire); addLight(tile,fire);
}
}
}
for(int i=0;i<block->plants.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);
}
} }

@ -2,7 +2,7 @@
#define RENDERER_LIGHT_INCLUDED #define RENDERER_LIGHT_INCLUDED
#include "renderer_opengl.hpp" #include "renderer_opengl.hpp"
#include "Types.h" #include "Types.h"
#include <map>
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)
@ -59,7 +59,7 @@ public:
}; };
virtual void resize(int32_t w, int32_t h) { virtual void resize(int32_t w, int32_t h) {
renderer_wrap::resize(w,h); renderer_wrap::resize(w,h);
reinitLightGrid(w,h); reinitLightGrid();
} }
}; };
class lightingEngine class lightingEngine
@ -79,7 +79,21 @@ struct lightSource
{ {
lightCell power; lightCell power;
int radius; 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 class lightingEngineViewscreen:public lightingEngine
{ {
@ -96,6 +110,8 @@ private:
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);
void initRawSpecific();
size_t inline getIndex(int x,int y) size_t inline getIndex(int x,int y)
{ {
return x*h+y; return x*h+y;
@ -103,6 +119,11 @@ private:
std::vector<lightCell> lightMap; std::vector<lightCell> lightMap;
std::vector<lightCell> ocupancy; std::vector<lightCell> ocupancy;
std::vector<lightSource> lights; std::vector<lightSource> lights;
std::map<int,lightSource> glowPlants;
std::map<int,lightSource> glowVeins;
int w,h; int w,h;
DFHack::rect2d mapPort; DFHack::rect2d mapPort;
}; };

@ -222,6 +222,10 @@ struct lightCell
{ {
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)
{
return r<other.r && g<other.g && b<other.b;
}
}; };
struct renderer_test : public renderer_wrap { struct renderer_test : public renderer_wrap {
private: private:

@ -20,7 +20,7 @@ using std::vector;
using std::string; using std::string;
enum RENDERER_MODE enum RENDERER_MODE
{ {
MODE_DEFAULT,MODE_TRIPPY,MODE_TRUECOLOR,MODE_LUA,MODE_LIGHT MODE_DEFAULT,MODE_TRIPPY,MODE_TRUECOLOR,MODE_LUA,MODE_LIGHT,MODE_LIGHT_OFF
}; };
RENDERER_MODE current_mode=MODE_DEFAULT; RENDERER_MODE current_mode=MODE_DEFAULT;
lightingEngine *engine=NULL; lightingEngine *engine=NULL;
@ -47,12 +47,6 @@ void removeOld()
if(current_mode!=MODE_DEFAULT) if(current_mode!=MODE_DEFAULT)
delete df::global::enabler->renderer; delete df::global::enabler->renderer;
current_mode=MODE_DEFAULT; current_mode=MODE_DEFAULT;
if(current_mode==MODE_LIGHT)
{
if(engine)
delete engine;
engine=0;
}
} }
void installNew(df::renderer* r,RENDERER_MODE newMode) void installNew(df::renderer* r,RENDERER_MODE newMode)
{ {
@ -241,6 +235,11 @@ static command_result rendermax(color_ostream &out, vector <string> & parameters
{ {
if(parameters.size()==0) if(parameters.size()==0)
return CR_WRONG_USAGE; 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]; string cmd=parameters[0];
if(cmd=="trippy") if(cmd=="trippy")
{ {
@ -305,26 +304,20 @@ static command_result rendermax(color_ostream &out, vector <string> & parameters
} }
else if(cmd=="light") else if(cmd=="light")
{ {
if(current_mode==MODE_LIGHT) removeOld();
{ renderer_light *myRender=new renderer_light(df::global::enabler->renderer);
engine->calculate(); installNew(myRender,MODE_LIGHT);
engine->updateWindow(); engine=new lightingEngineViewscreen(myRender);
} engine->calculate();
else 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; return CR_OK;
} }
else if(cmd=="disable") else if(cmd=="disable")
{ {
if(current_mode==MODE_DEFAULT) if(current_mode==MODE_DEFAULT)
out.print("%s\n","Not installed, doing nothing."); out.print("%s\n","Not installed, doing nothing.");
else if(current_mode==MODE_LIGHT)
current_mode=MODE_LIGHT_OFF;
else else
removeOld(); removeOld();
@ -336,9 +329,19 @@ DFhackCExport command_result plugin_onupdate (color_ostream &out)
{ {
if(engine) if(engine)
{ {
engine->calculate(); if(current_mode==MODE_LIGHT_OFF)
engine->updateWindow(); {
delete engine;
engine=0;
removeOld();
}
else
{
engine->calculate();
engine->updateWindow();
}
} }
return CR_OK; return CR_OK;
} }
DFhackCExport command_result plugin_shutdown(color_ostream &) DFhackCExport command_result plugin_shutdown(color_ostream &)