View Single Post
Re: code to get the illumination at any point on the map
Old
  (#38)
KWo
Developer of PODBot mm
 
KWo's Avatar
 
Status: Offline
Posts: 3,425
Join Date: Apr 2004
Default Re: code to get the illumination at any point on the map - 21-03-2012

Finally I've got it compiling even with such code:
bot_globals.h
Code:
#include <com_model.h>
#include <pm_defs.h>

// KWo - 13.03.2012 - Thanks to Immortal_BLG for light code

#define   SURF_PLANEBACK      2
#define   SURF_DRAWSKY        4
#define   SURF_DRAWSPRITE     8
#define   SURF_DRAWTURB       0x10
#define   SURF_DRAWTILED      0x20
#define   SURF_DRAWBACKGROUND 0x40

#ifdef __linux__
// Linux doesn't have this function so this emulates its functionality
inline void *GetModuleHandle(const char *name)
{
   void *handle;

   if( name == NULL )
   {
      // hmm, how can this be handled under linux....
      // is it even needed?
      return NULL;
   }

    if( (handle=dlopen(name, RTLD_NOW))==NULL)
    {
            // couldn't open this file
            return NULL;
    }

   // read "man dlopen" for details
   // in short dlopen() inc a ref count
   // so dec the ref count by performing the close
   dlclose(handle);
   return handle;
}
#endif

struct GL_msurface_t
{
#define SURF_UNDERWATER      0x80   // ONLY FOR OpenGL!!!
//#define SURF_DONTWARP      0x100   // ONLY FOR OpenGL!!! (EXISTS?!?!?!?!?!??!?!?!?!?!?!??!)

/*off=0(0)*/   int         visframe;      // should be drawn when node is crossed
/*off=4(1)*/   mplane_t   *plane;         // pointer to shared plane
/*off=8(2)*/   int         flags;         // see SURF_* #defines

/*off=12(3)*/   int         firstedge;   // look up in model->surfedges[], negative numbers are backwards edges
/*off=16(4)*/   int         numedges;

/*off=20(5)*/   short      texturemins[2]; // smallest s/t position on the surface.
/*off=24(6)*/   short      extents[2];      // ?? s/t texture size, 1..256 for all non-sky surfaces

/*off=28(7)*/   int         light_s, light_t;   // gl lightmap coordinates
/*off=36(9)*/   struct glpoly_t   *polys;            // multiple if warped
/*off=40(10)*/   msurface_t   *texturechain;
/*off=44(11)*/   mtexinfo_t   *texinfo;

// lighting info
/*off=48(12)*/   int         dlightframe;   // last frame the surface was checked by an animated light
/*off=52(13)*/   int         dlightbits;      // dynamically generated. Indicates if the surface illumination
                        // is modified by an animated light.
/*off=56(14)*/   int         lightmaptexturenum;
/*off=60(15)*/   unsigned char      styles[MAXLIGHTMAPS]; // index into d_lightstylevalue[] for animated lights
                             // no one surface can be effected by more than 4
                             // animated lights.

/*off=64(16)*/   int         cached_light[MAXLIGHTMAPS];   // values currently used in lightmap
/*off=80(20)*/   qboolean   cached_dlight;            // true if dynamic light in cache

/*off=84(21)*/   color24      *samples;   // [numstyles*surfsize]

/*off=88(22)*/   decal_t      *pdecals;
};   // sizeof (GL_msurface_t) == 92 (23)
struct GL_mnode_t
{
   enum ChildrenType_t
   {
      ChildrenType_Front,
      ChildrenType_Back,

      ChildrenType_Total
   };

// common with leaf
/*! Off=0(0)*/   int         contents;      // 0, to differentiate from leafs
/*! Off=4(1)*/   int         visframe;      // node needs to be traversed if current

/*! Off=8(2)*/   Vector      mins, maxs;      // for bounding box culling

/*! Off=32(8)*/   mnode_t   *parent;

// node specific
/*! Off=36(9)*/   mplane_t   *plane;
/*! Off=40(10)*/   mnode_t   *children[ChildrenType_Total];

/*! Off=48(12)*/   unsigned short      firstsurface;
/*! Off=50(12.5)*/   unsigned short      numsurfaces;
};   // sizeof (GL_mnode_t) == 52 (13)

#define   MAX_LIGHTSTYLES   64
#define   MAX_LIGHTSTYLEVALUE   256

struct lightstyle_t
{
   int  length;
   char map[MAX_LIGHTSTYLES];
};

extern lightstyle_t cl_lightstyle[MAX_LIGHTSTYLES];
extern int          d_lightstylevalue[MAX_LIGHTSTYLEVALUE];   // 8.8 fraction of base light value
extern model_t     *sv_worldmodel;   // Analog of sv.worldmodel.

struct Color
{
   int red;
   int green;
   int blue;

   inline       void         Reset  (void)       { red = green = blue = 0; }
   inline const unsigned int GetAvg (void) const { return (red + green + blue) / (sizeof (Color) / sizeof (int)); }
};

/*
=============================================================================

LIGHT SAMPLING

=============================================================================
*/


namespace Light
{
//extern const mplane_t *lightplane (NULL);
//extern Vector lightspot;
   extern Color g_pointColor;

//   extern const bool RecursiveLightPoint (const nodeType *const node, const Vector &start, const Vector &end);

//      Color g_pointColor;
//
   template <typename nodeType, typename surfaceType> extern const  bool RecursiveLightPoint (const nodeType *const node, const Vector  &start, const Vector &end)
   {
      float front, back, frac;
      int side;
      mplane_t *plane;
      Vector mid;
      surfaceType *surf;
      int s, t, ds, dt;
      int i;
      mtexinfo_t *tex;
      color24 *lightmap;
      unsigned int scale;
      unsigned char maps;

      // Reliability check.
      assert (node != NULL);

      if (node->contents < 0)
         return false;   // didn't hit anything

      // Determine which side of the node plane our points are on
      // FIXME: optimize for axial
      plane = node->plane;
      front = DotProduct (start, plane->normal) - plane->dist;
      back = DotProduct (end, plane->normal) - plane->dist;
      side = front < 0.0f;

      // If they're both on the same side of the plane, don't bother to split just check the appropriate child
      if ((back < 0.0f) == side)
         return RecursiveLightPoint <nodeType, surfaceType>  (reinterpret_cast <nodeType *> (node->children[side]), start,  end);

      // calculate mid point
      frac = front / (front - back);
      mid = start + (end - start) * frac;

      // go down front side
      if (RecursiveLightPoint <nodeType, surfaceType>  (reinterpret_cast <nodeType *> (node->children[side]), start,  mid))
         return true;   // hit something

      // Blow it off if it doesn't split the plane...
      if ((back < 0.0f) == side)
         return false;   // didn't hit anything

      // check for impact on this node
   //   lightspot = mid;
   //   lightplane = plane;

      surf = reinterpret_cast <surfaceType *> (sv_worldmodel->surfaces) + node->firstsurface;
      for (i = 0; i < node->numsurfaces; ++i, ++surf)
      {
         if (surf->flags & SURF_DRAWTILED)
            continue;   // no lightmaps

         tex = surf->texinfo;

         // See where in lightmap space our intersection point is
         s = static_cast <int> (DotProduct (mid, Vector (tex->vecs[0])) + tex->vecs[0][3]);
         t = static_cast <int> (DotProduct (mid, Vector (tex->vecs[1])) + tex->vecs[1][3]);

         // Not in the bounds of our lightmap? punt...
         if (s < surf->texturemins[0] || t < surf->texturemins[1])
            continue;

         // assuming a square lightmap (FIXME: which ain't always the case),
         // lets see if it lies in that rectangle. If not, punt...
         ds = s - surf->texturemins[0];
         dt = t - surf->texturemins[1];

         if (ds > surf->extents[0] || dt > surf->extents[1])
            continue;

         if (surf->samples == NULL)
            return true;

         ds >>= 4;
         dt >>= 4;

         g_pointColor.Reset ();   // Reset point color.

         const int smax ((surf->extents[0] >> 4) + 1);
         const int tmax ((surf->extents[1] >> 4) + 1);
         const int size (smax * tmax);

         lightmap = surf->samples + dt * smax + ds;

         // Compute the lightmap color at a particular point
         for (maps = 0u; maps < MAXLIGHTMAPS && surf->styles[maps] != 255u; ++maps)
         {
            scale = d_lightstylevalue[surf->styles[maps]];

            g_pointColor.red += lightmap->r * scale;
            g_pointColor.green += lightmap->g * scale;
            g_pointColor.blue += lightmap->b * scale;

            lightmap += size;   // skip to next lightmap
         }

         g_pointColor.red >>= 8u;
         g_pointColor.green >>= 8u;
         g_pointColor.blue >>= 8u;

         return true;
      }

      // go down back side
      return RecursiveLightPoint <nodeType, surfaceType>  (reinterpret_cast <nodeType *> (node->children[!side]), mid,  end);
   }

   inline const bool IsSoftwareDrawingMode (void)
   {
      static const bool isSoftwareDrawingMode (IS_DEDICATED_SERVER () || GetModuleHandle ("sw.dll") != NULL);

      return isSoftwareDrawingMode;
   }

   inline const bool ActualRecursiveLightPoint (const Vector &start, const Vector &end)
   {
      return IsSoftwareDrawingMode () ?
         RecursiveLightPoint <mnode_t, msurface_t> (sv_worldmodel->nodes, start, end) :
         RecursiveLightPoint <GL_mnode_t, GL_msurface_t>  (reinterpret_cast <GL_mnode_t *> (sv_worldmodel->nodes), start,  end);
   }

   inline const unsigned char R_LightPoint (const Vector &p)
   {
   // Reliability check.
      if (sv_worldmodel == NULL)
         return 0u;

      if (sv_worldmodel->lightdata == NULL)
         return 255u;

      Vector end (p);

      end.z -= 2048.0f;

      return ActualRecursiveLightPoint (p, end) == false ? 0u : static_cast <unsigned char> (g_pointColor.GetAvg ());
   }
}
bot_globals.cpp
Code:
lightstyle_t cl_lightstyle[MAX_LIGHTSTYLES];
int          d_lightstylevalue[MAX_LIGHTSTYLEVALUE];   // 8.8 fraction of base light value
model_t     *sv_worldmodel (NULL);   // Analog of sv.worldmodel.

namespace Light
{
   Color g_pointColor;
   template <typename nodeType, typename surfaceType> const bool RecursiveLightPoint (const nodeType *const node, const Vector &start, const Vector &end);
}
The stupid message about wrong reference was coming from old compiled bot.cpp.obj, which wasn't changed by me long time, but it had already linked some references to the function defined first way (when it was compiling correctly for MS C++ Visual Express 200. After that I was using all the time the "Rebuild" function (as usually), which should compile newer files only. If headers file were changed, all cpp should be compiled again, but it looks it didn't work correctly for MinGW. The "Clean" command helped. After that I did "Build" and it compiled the dll correctly (it is loading and light code is working for windows). I have to check how about cygwin and linux.
Thanks again for the patience for me.
  
Reply With Quote