LCOV - code coverage report
Current view: top level - engine/world - dynlight.cpp (source / functions) Hit Total Coverage
Test: Libprimis Test Coverage Lines: 0 101 0.0 %
Date: 2024-11-22 05:07:59 Functions: 0 10 0.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, vec(0, 0, 0), 0, false))
     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 1.14