#ifndef RENDERER_LIGHT_INCLUDED #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) { const int tile = x*(df::global::gps->dimy) + y; old_opengl* p=reinterpret_cast(parent); float *fg = p->fg + tile * 4 * 6; float *bg = p->bg + tile * 4 * 6; float *tex = p->tex + tile * 2 * 6; lightCell light=lightGrid[tile]; for (int i = 0; i < 6; i++) { *(fg++) *= light.r; *(fg++) *= light.g; *(fg++) *= light.b; *(fg++) = 1; *(bg++) *= light.r; *(bg++) *= light.g; *(bg++) *= light.b; *(bg++) = 1; } } void reinitLightGrid(int w,int h) { tthread::lock_guard guard(dataMutex); lightGrid.resize(w*h); } void reinitLightGrid() { reinitLightGrid(df::global::gps->dimy,df::global::gps->dimx); } public: tthread::fast_mutex dataMutex; std::vector lightGrid; renderer_light(renderer* parent):renderer_wrap(parent) { reinitLightGrid(); } virtual void update_tile(int32_t x, int32_t y) { renderer_wrap::update_tile(x,y); tthread::lock_guard guard(dataMutex); colorizeTile(x,y); }; virtual void update_all() { renderer_wrap::update_all(); tthread::lock_guard guard(dataMutex); for (int x = 0; x < df::global::gps->dimx; x++) for (int y = 0; y < df::global::gps->dimy; y++) colorizeTile(x,y); }; virtual void grid_resize(int32_t w, int32_t h) { renderer_wrap::grid_resize(w,h); reinitLightGrid(w,h); }; virtual void resize(int32_t w, int32_t h) { renderer_wrap::resize(w,h); reinitLightGrid(); } }; class lightingEngine { public: lightingEngine(renderer_light* target):myRenderer(target){} virtual void reinit()=0; virtual void calculate()=0; virtual void updateWindow()=0; virtual void loadSettings()=0; protected: renderer_light* myRenderer; }; struct lightSource { lightCell power; int radius; 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); }; struct matLightDef { int mat_index; int mat_type; bool isTransparent; lightCell transparency; bool isEmiting; bool sizeModifiesPower; bool sizeModifiesRange; bool flicker; lightCell emitColor; int radius; matLightDef(){} matLightDef(lightCell transparency,lightCell emit,int rad):isTransparent(true),isEmiting(true), transparency(transparency),emitColor(emit),radius(rad){} matLightDef(lightCell emit,int rad):isTransparent(false),isEmiting(true),emitColor(emit),radius(rad){} matLightDef(lightCell transparency):isTransparent(true),isEmiting(false),transparency(transparency){} lightSource makeSource(float size=1) const { //TODO implement sizeModifiesPower/range return lightSource(emitColor,radius); } }; class lightingEngineViewscreen:public lightingEngine { public: lightingEngineViewscreen(renderer_light* target); void reinit(); void calculate(); void updateWindow(); void loadSettings(); private: void doOcupancyAndLights(); 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); //apply material to cell 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. 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; } //maps std::vector lightMap; std::vector ocupancy; std::vector lights; //settings ///set up sane settings if setting file does not exist. void defaultSettings(); static int parseMaterials(lua_State* L); static int parseSpecial(lua_State* L); //special stuff matLightDef matLava; matLightDef matIce; matLightDef matAmbience; matLightDef matCursor; //materials std::map,matLightDef> matDefs; int w,h; DFHack::rect2d mapPort; }; #endif