LCOV - code coverage report
Current view: top level - engine/world - dynlight.cpp (source / functions) Coverage Total Hit
Test: Libprimis Test Coverage Lines: 0.0 % 101 0
Test Date: 2025-08-24 05:32:49 Functions: 0.0 % 10 0

            Line data    Source code
       1              : /* dynlight.cpp: handling of changing lights
       2              :  *
       3              :  * while the lighting system is dynamic, the changing state of the light entities
       4              :  * for the renderer to handle must be updated with new values that reflect the type
       5              :  * of light to be drawn
       6              :  *
       7              :  * this includes pulsating lights (which change in radius dynamically)
       8              :  * and multicolored lights (which change hue dynamically)
       9              :  */
      10              : #include "../libprimis-headers/cube.h"
      11              : #include "../../shared/geomexts.h"
      12              : 
      13              : #include "dynlight.h"
      14              : #include "physics.h"
      15              : 
      16              : #include "interface/control.h"
      17              : 
      18              : #include "render/rendergl.h"
      19              : #include "render/renderva.h"
      20              : 
      21              : //internally relevant functionality
      22              : namespace
      23              : {
      24              :     VARNP(dynlights, usedynlights, 0, 1, 1); //toggle using dynamic lights
      25              :     VARP(dynlightdist, 0, 1024, 10000); //distance after which dynamic lights are not rendered (1024 = 128m)
      26              : 
      27              :     class dynlight final
      28              :     {
      29              :         public:
      30              :             vec o;
      31              :             float curradius, dist;
      32              :             int expire;
      33              :             const physent *owner;
      34              : 
      35            0 :             dynlight(vec o, int expire, physent *owner, float radius, float initradius, vec color, vec initcolor, int fade, int peak, int flags, vec dir, int spot) :
      36            0 :                 o(o), expire(expire), owner(owner), radius(radius), initradius(initradius), color(color), initcolor(initcolor), fade(fade), peak(peak), flags(flags), dir(dir), spot(spot)
      37              :             {
      38            0 :             }
      39              : 
      40            0 :             void calcradius()
      41              :             {
      42            0 :                 if(fade + peak > 0)
      43              :                 {
      44            0 :                     int remaining = expire - lastmillis;
      45            0 :                     if(flags&DynLight_Expand)
      46              :                     {
      47            0 :                         curradius = initradius + (radius - initradius) * (1.0f - remaining/static_cast<float>(fade + peak));
      48              :                     }
      49            0 :                     else if(!(flags&DynLight_Flash) && remaining > fade)
      50              :                     {
      51            0 :                         curradius = initradius + (radius - initradius) * (1.0f - static_cast<float>(remaining - fade)/peak);
      52              :                     }
      53            0 :                     else if(flags&DynLight_Shrink)
      54              :                     {
      55            0 :                         curradius = (radius*remaining)/fade;
      56              :                     }
      57              :                     else
      58              :                     {
      59            0 :                         curradius = radius;
      60              :                     }
      61              :                 }
      62              :                 else
      63              :                 {
      64            0 :                     curradius = radius;
      65              :                 }
      66            0 :             }
      67              : 
      68            0 :             void calccolor()
      69              :             {
      70            0 :                 if(flags&DynLight_Flash || peak <= 0)
      71              :                 {
      72            0 :                     curcolor = color;
      73              :                 }
      74              :                 else
      75              :                 {
      76            0 :                     int peaking = expire - lastmillis - fade;
      77            0 :                     if(peaking <= 0)
      78              :                     {
      79            0 :                         curcolor = color;
      80              :                     }
      81              :                     else
      82              :                     {
      83            0 :                         curcolor.lerp(initcolor, color, 1.0f - static_cast<float>(peaking)/peak);
      84              :                     }
      85              :                 }
      86            0 :                 float intensity = 1.0f;
      87            0 :                 if(fade > 0)
      88              :                 {
      89            0 :                     int fading = expire - lastmillis;
      90            0 :                     if(fading < fade)
      91              :                     {
      92            0 :                         intensity = static_cast<float>(fading)/fade;
      93              :                     }
      94              :                 }
      95            0 :                 curcolor.mul(intensity);
      96            0 :             }
      97              : 
      98              :             /**
      99              :              * @brief gets information about this dynlight
     100              :              *
     101              :              *  @param n the nth closest dynamic light
     102              :              *  @param o a reference to set as the location of the specified dynlight
     103              :              *  @param radius a reference to set as the radius of the specified dynlight
     104              :              *  @param color a reference to set as the color of the specifeid dynlight
     105              :              *  @param spot a reference to the spotlight information of the dynlight
     106              :              *  @param dir a reference to set as the direction the dynlight is pointing
     107              :              *  @param flags a reference to the flag bitmap for the dynlight
     108              :              */
     109            0 :             void dynlightinfo(vec &origin, float &radius, vec &color, vec &direction, int &spotlight, int &flagmask) const
     110              :             {
     111            0 :                 origin = o;
     112            0 :                 radius = curradius;
     113            0 :                 color = curcolor;
     114            0 :                 spotlight = spot;
     115            0 :                 direction = dir;
     116            0 :                 flagmask = flags & 0xFF;
     117            0 :             }
     118              : 
     119              :         private:
     120              :             float radius, initradius;
     121              :             vec color, initcolor, curcolor;
     122              :             int fade, peak, flags;
     123              :             vec dir;
     124              :             int spot;
     125              :     };
     126              : 
     127              :     std::vector<dynlight> dynlights;
     128              :     std::vector<const dynlight *> closedynlights;
     129              : 
     130              :     //cleans up dynlights, deletes dynlights contents once none have expire field
     131            0 :     void cleardynlights()
     132              :     {
     133            0 :         int faded = -1;
     134            0 :         for(size_t i = 0; i < dynlights.size(); i++)
     135              :         {
     136            0 :             if(lastmillis<dynlights[i].expire)
     137              :             {
     138            0 :                 faded = i;
     139            0 :                 break;
     140              :             }
     141              :         }
     142            0 :         if(faded<0) //if any light has lastmillis > expire field
     143              :         {
     144            0 :             dynlights.clear();
     145              :         }
     146            0 :         else if(faded>0)
     147              :         {
     148            0 :             dynlights.erase(dynlights.begin(), dynlights.begin() + faded);
     149              :         }
     150            0 :     }
     151              : }
     152              : //externally relevant functionality
     153              : 
     154              : //adds a dynamic light object to the dynlights vector with the attributes indicated (radius, color, fade, peak, flags, etc..)
     155            0 : void adddynlight(const vec &o, float radius, const vec &color, int fade, int peak, int flags, float initradius, const vec &initcolor, physent *owner, const vec &dir, int spot)
     156              : {
     157            0 :     if(!usedynlights)
     158              :     {
     159            0 :         return;
     160              :     }
     161            0 :     if(o.dist(camera1->o) > dynlightdist || radius <= 0)
     162              :     {
     163            0 :         return;
     164              :     }
     165            0 :     int insert = 0,
     166            0 :         expire = fade + peak + lastmillis;
     167            0 :     for(int i = dynlights.size(); --i >=0;) //note reverse iteration
     168              :     {
     169            0 :         if(expire>=dynlights[i].expire)
     170              :         {
     171            0 :             insert = i+1;
     172            0 :             break;
     173              :         }
     174              :     }
     175            0 :     dynlight d(o, expire, owner, radius, initradius, color, initcolor, fade, peak, flags, dir, spot);
     176            0 :     dynlights.insert(dynlights.begin() + insert, d);
     177              : }
     178              : 
     179            0 : void removetrackeddynlights(const physent *owner)
     180              : {
     181            0 :     for(int i = dynlights.size(); --i >=0;) //note reverse iteration
     182              :     {
     183            0 :         if(owner ? dynlights[i].owner == owner : dynlights[i].owner != nullptr)
     184              :         {
     185            0 :             dynlights.erase(dynlights.begin() + i);
     186              :         }
     187              :     }
     188            0 : }
     189              : 
     190              : //finds which dynamic lights are near enough and are visible to the player
     191              : //returns the number of lights (and sets `closedynlights` vector contents to the appropriate nearby light ents)
     192            0 : size_t finddynlights()
     193              : {
     194            0 :     closedynlights.clear();
     195            0 :     if(!usedynlights)
     196              :     {
     197            0 :         return 0;
     198              :     }
     199            0 :     physent e;
     200            0 :     e.type = physent::PhysEnt_Camera;
     201            0 :     for(dynlight &d : dynlights)
     202              :     {
     203            0 :         if(d.curradius <= 0)
     204              :         {
     205            0 :             continue;
     206              :         }
     207            0 :         d.dist = camera1->o.dist(d.o) - d.curradius;
     208            0 :         if(d.dist > dynlightdist || view.isfoggedsphere(d.curradius, d.o))
     209              :         {
     210            0 :             continue;
     211              :         }
     212            0 :         e.o = d.o;
     213            0 :         e.radius = e.xradius = e.yradius = e.eyeheight = e.aboveeye = d.curradius;
     214            0 :         if(!collide(&e, nullptr, vec(0, 0, 0), 0))
     215              :         {
     216            0 :             continue;
     217              :         }
     218            0 :         int insert = 0;
     219            0 :         for(int i = closedynlights.size(); --i >=0;) //note reverse iteration
     220              :         {
     221            0 :             if(d.dist >= closedynlights[i]->dist)
     222              :             {
     223            0 :                 insert = i+1;
     224            0 :                 break;
     225              :             }
     226              :         }
     227            0 :         closedynlights.insert(closedynlights.begin() + insert, &d);
     228              :     }
     229            0 :     return closedynlights.size();
     230              : }
     231              : 
     232            0 : bool getdynlight(size_t n, vec &o, float &radius, vec &color, vec &dir, int &spot, int &flags)
     233              : {
     234            0 :     if(!(closedynlights.size() > n))
     235              :     {
     236            0 :         return false;
     237              :     }
     238            0 :     const dynlight &d = *closedynlights[n];
     239            0 :     d.dynlightinfo(o, radius, color, dir, spot, flags);
     240            0 :     return true;
     241              : }
     242              : 
     243            0 : void updatedynlights()
     244              : {
     245            0 :     cleardynlights();
     246            0 :     for(dynlight &d : dynlights)
     247              :     {
     248            0 :         d.calcradius();
     249            0 :         d.calccolor();
     250              :     }
     251            0 : }
        

Generated by: LCOV version 2.0-1