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-11-24 07:55:42 Functions: 0.0 % 10 0

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

Generated by: LCOV version 2.0-1