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-02-18 06:21:28 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
      28              :     {
      29              :         public:
      30              : 
      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              :         /* dynlightinfo: gets information about this dynlight
     100              :          *
     101              :          * Parameters:
     102              :          *  n: the nth closest dynamic light
     103              :          *  o: a reference to set as the location of the specified dynlight
     104              :          *  radius: a reference to set as the radius of the specified dynlight
     105              :          *  color: a reference to set as the color of the specifeid dynlight
     106              :          *  spot: a reference to the spotlight information of the dynlight
     107              :          *  dir: a reference to set as the direction the dynlight is pointing
     108              :          *  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              :         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(uint 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              : /* getdynlight: gets the nth dynlight near camera and sets references to its values
     233              :  *
     234              :  * Parameters:
     235              :  *  n: the nth closest dynamic light
     236              :  *  o: a reference to set as the location of the specified dynlight
     237              :  *  radius: a reference to set as the radius of the specified dynlight
     238              :  *  color: a reference to set as the color of the specifeid dynlight
     239              :  *  spot: a reference to the spotlight information of the dynlight
     240              :  *  dir: a reference to set as the direction the dynlight is pointing
     241              :  *  flags: a reference to the flag bitmap for the dynlight
     242              :  * Returns:
     243              :  *  bool: true if light at position n was found, false otherwise
     244              :  *
     245              :  */
     246            0 : bool getdynlight(size_t n, vec &o, float &radius, vec &color, vec &dir, int &spot, int &flags)
     247              : {
     248            0 :     if(!(closedynlights.size() > n))
     249              :     {
     250            0 :         return false;
     251              :     }
     252            0 :     const dynlight &d = *closedynlights[n];
     253            0 :     d.dynlightinfo(o, radius, color, dir, spot, flags);
     254            0 :     return true;
     255              : }
     256              : 
     257            0 : void updatedynlights()
     258              : {
     259            0 :     cleardynlights();
     260            0 :     for(dynlight &d : dynlights)
     261              :     {
     262            0 :         d.calcradius();
     263            0 :         d.calccolor();
     264              :     }
     265            0 : }
        

Generated by: LCOV version 2.0-1