Inside3D!
     

Ambient occlusion on Quake lightmaps

 
Post new topic   Reply to topic    Inside3d Forums Forum Index -> General Programming
View previous topic :: View next topic  
Author Message
JasonX



Joined: 21 Apr 2009
Posts: 89

PostPosted: Fri Mar 26, 2010 6:33 pm    Post subject: Ambient occlusion on Quake lightmaps Reply with quote

I was thinking about this and noticed that, maybe, Quake map compilers should run an Ambient occlusion pass, just like Q3Map2 does (-dirty). Has it been done yet?
Back to top
View user's profile Send private message
Teiman



Joined: 03 Jun 2007
Posts: 309

PostPosted: Fri Mar 26, 2010 7:15 pm    Post subject: Reply with quote

Anything that combat the "tile based" look of most maps will be good in my untrained eyes.
Back to top
View user's profile Send private message
metlslime



Joined: 05 Feb 2008
Posts: 177

PostPosted: Fri Mar 26, 2010 7:25 pm    Post subject: Reply with quote

I got this working a few years ago, but it's kind of hacked into bjp's light tool and not really in a releasable state. Plus it really needs optimization.

But yeah, it's a good idea, it makes outdoor areas look nicer.
Back to top
View user's profile Send private message
JasonX



Joined: 21 Apr 2009
Posts: 89

PostPosted: Fri Mar 26, 2010 7:48 pm    Post subject: Reply with quote

Here's the "dirty" feature from Q3Map2, their ambient occlusion implementation.

Line 1442: https://zerowing.idsoftware.com/svn/radiant/GtkRadiant/trunk/tools/quake3/q3map2/light_ydnar.c
Back to top
View user's profile Send private message
LordHavoc



Joined: 05 Nov 2004
Posts: 243
Location: western Oregon, USA

PostPosted: Mon Mar 29, 2010 9:25 pm    Post subject: Reply with quote

The (experimental and unusable - it doesn't save! and it's only meant for q3bsp at the moment) mod_generatelightmaps code in DP does ambient occlusion in a somewhat interesting and fast way...

It builds an svbsp tree for each light, so it know precisely where shadows are in a geometric sense, but then instead of sampling that directly, it jitters the world position of each lightmap sample with a series of fixed offsets (randomly generated at start, but fixed during a run), this gives the characteristic ambient occlusion and antialiasing at the same time.
Back to top
View user's profile Send private message Visit poster's website
reckless



Joined: 24 Jan 2008
Posts: 390
Location: inside tha debugger

PostPosted: Fri Apr 02, 2010 2:48 am    Post subject: Reply with quote

hmm i wonder if that was what the codebit i found in bakers quake2 was for ?

as far as i could read from it it also parses the bsp tree and saves it as a cached version (bit like the old .ms files but with .bsp extension).

Code:


void Mod_LoadAliasModel(model_t * mod, void *buffer)
{
   int            i, j;
   dmdl_t         *pinmodel, *pheader;
   dstvert_t      *pinst, *poutst;
   dtriangle_t      *pintri, *pouttri, *tris;
   daliasframe_t   *pinframe, *poutframe;
   int            *pincmd, *poutcmd;
   int            version;
   
   vec3_t         tempr, tempv;
   int            k,l;
   char         nam[MAX_OSPATH];
   char         *buff;

   daliasframe_t   *frame;
   dtrivertx_t      *verts;
   byte         *norms = NULL, *tangents, *binormals;
   float         s, t;
   float         iw, ih;
   fstvert_t      *st;
   byte         smooth;
   int            ax, cx;
   vec3_t         binormals_[MAX_VERTS];
   vec3_t         tangents_[MAX_VERTS];
   char         cachename[MAX_OSPATH];
   FILE         *f;
   unsigned      checksum, cs_binormals, cs_tangents;
   qboolean      success = false, cache = false, err = true;;
   
   mod->memorySize = 0;

   pinmodel = (dmdl_t *) buffer;

   version = LittleLong(pinmodel->version);
   if (version != ALIAS_VERSION)
      VID_Error(ERR_DROP, "%s has wrong version number (%i should be %i)", mod->name, version, ALIAS_VERSION);
   
   pheader = Hunk_Alloc(LittleLong(pinmodel->ofs_end));
   
   mod->memorySize += LittleLong(pinmodel->ofs_end);
   
   aliasSize += mod->memorySize;

   // byte swap the header fields and sanity check
   for (i = 0; i < sizeof(dmdl_t) * 0.25; i++)
      ((int *) pheader)[i] = LittleLong(((int *) buffer)[i]);

   if (pheader->skinheight > MAX_LBM_HEIGHT)
      VID_Error(ERR_DROP, "model %s has a skin taller than %d",
              mod->name, MAX_LBM_HEIGHT);

   if (pheader->num_xyz <= 0)
      VID_Error(ERR_DROP, "model %s has no vertices", mod->name);

   if (pheader->num_xyz > MAX_VERTS)
      VID_Error(ERR_DROP, "model %s has too many vertices", mod->name);

   if (pheader->num_st <= 0)
      VID_Error(ERR_DROP, "model %s has no st vertices", mod->name);

   if (pheader->num_tris <= 0)
      VID_Error(ERR_DROP, "model %s has no triangles", mod->name);

   if (pheader->num_frames <= 0)
      VID_Error(ERR_DROP, "model %s has no frames", mod->name);

//
// load base s and t vertices (not used in gl version)
//
   pinst = (dstvert_t *) ((byte *) pinmodel + pheader->ofs_st);
   poutst = (dstvert_t *) ((byte *) pheader + pheader->ofs_st);

   for (i = 0; i < pheader->num_st; i++) {
      poutst[i].s = LittleShort(pinst[i].s);
      poutst[i].t = LittleShort(pinst[i].t);
   }

//
// load triangle lists
//
   pintri = (dtriangle_t *) ((byte *) pinmodel + pheader->ofs_tris);
   pouttri = (dtriangle_t *) ((byte *) pheader + pheader->ofs_tris);

   for (i = 0, tris = pouttri; i < pheader->num_tris; i++, tris++) {
      for (j = 0; j < 3; j++) {
         tris->index_xyz[j] = LittleShort(pintri[i].index_xyz[j]);
         tris->index_st[j] = LittleShort(pintri[i].index_st[j]);
      }
   }

   // find neighbours
   mod->neighbors = malloc(pheader->num_tris * sizeof(neighbors_t));
   Mod_BuildTriangleNeighbors(mod->neighbors, pouttri, pheader->num_tris);
   mod->memorySize += pheader->num_tris * sizeof(neighbors_t);
//
// load the frames
//
   for (i = 0; i < pheader->num_frames; i++) {
      pinframe = (daliasframe_t *) ((byte *) pinmodel + pheader->ofs_frames + i * pheader->framesize);
      poutframe =   (daliasframe_t *) ((byte *) pheader + pheader->ofs_frames + i * pheader->framesize);

      Q_memcpy(poutframe->name, pinframe->name, sizeof(poutframe->name));

      for (j = 0; j < 3; j++) {
         poutframe->scale[j] = LittleFloat(pinframe->scale[j]);
         poutframe->translate[j] = LittleFloat(pinframe->translate[j]);
      }

      // verts are all 8 bit, so no swapping needed
      Q_memcpy(poutframe->verts, pinframe->verts, pheader->num_xyz * sizeof(dtrivertx_t));
   }
   mod->type = mod_alias;

   //
   // load the glcmds
   //
   pincmd = (int *) ((byte *) pinmodel + pheader->ofs_glcmds);
   poutcmd = (int *) ((byte *) pheader + pheader->ofs_glcmds);

   for (i = 0; i < pheader->num_glcmds; i++) {
      poutcmd[i] = LittleLong(pincmd[i]);
   }

   // register all skins
   Q_memcpy((char *) pheader + pheader->ofs_skins, (char *) pinmodel + pheader->ofs_skins, pheader->num_skins * MAX_SKINNAME);
   
   for (i = 0; i < pheader->num_skins; i++) {
      char *pname;
      char gl[48];
      
      pname = (char *) pheader + pheader->ofs_skins + i * MAX_SKINNAME;
      mod->skins[i] = GL_FindImage(pname, it_skin);
      
      // GlowMaps loading
      Q_strcpy(gl, pname);
      gl[strlen(gl) - 4] = 0;
      Q_strcat(gl, "_gl.tga");
      mod->glowtexture[i] = GL_FindImage(gl, it_skin);

      if(!mod->glowtexture[i]){
      Q_strcpy(gl, pname);
      gl[strlen(gl) - 4] = 0;
      Q_strcat(gl, "_gl.png");
      mod->glowtexture[i] = GL_FindImage(gl, it_skin);
      }

      // Loading Normal maps
      Q_strcpy(gl, pname);
      gl[strlen(gl) - 4] = 0;
      Q_strcat(gl, "_nm.dds");
      mod->skins_normal[i] = GL_FindImage(gl, it_wall);
      
      if (!mod->skins_normal[i]){
        Q_strcpy(gl, pname);
        gl[strlen(gl) - 4] = 0;
        Q_strcat(gl, "_nm.tga");
        mod->skins_normal[i] = GL_FindImage(gl, it_wall);
      }
      
      Q_strcpy(gl, pname);
      gl[strlen(gl) - 4] = 0;
      Q_strcat(gl, "_env.tga");
      mod->skin_env[i] = GL_FindImage(gl, it_skin);      
   }
   mod->flags = 0;

   // set default render fx values
   mod->ambient = r_ambientLevel->value;
   mod->diffuse = r_diffuseLevel->value;
   mod->specular = r_specularScale->value;
   mod->glowCfg[0] = 0.3;
   mod->glowCfg[1] = 1.0;
   mod->glowCfg[2] = 5.666;
   mod->noselfshadow = false;
   mod->envmap = false;

   i = strlen(mod->name);
   memcpy(nam, mod->name, i);
   nam[i-3]='r';
   nam[i-2]='f';
   nam[i-1]='x';
   nam[i]=0;

   // load the .rfx
   i = FS_LoadFile (nam, (void **)&buff);

   if (buff)
   {
      char bak=buff[i];
      buff[i] = 0;
      Mod_LoadAliasModelFx(mod, buff);
      buff[i] = bak;
      FS_FreeFile (buff);
   }
   
   // Calculate texcoords for triangles (for compute tangents and binormals)
   tris = (dtriangle_t *) ((byte *)pheader + pheader->ofs_tris);
   mod->st = st = (fstvert_t*)Hunk_Alloc (pheader->num_st * sizeof(fstvert_t));
   mod->memorySize += pheader->num_st * sizeof(fstvert_t);
   iw = 1.0 / pheader->skinwidth;
   ih = 1.0 / pheader->skinheight;

   for (i=0; i<pheader->num_st ; i++)
   {
      s = poutst[i].s;
      t = poutst[i].t;
      st[i].s = (s - 0.5) * iw;
      st[i].t = (t - 0.5) * ih;
   }

   // create the cache directory
   Q_sprintf (cachename, sizeof(cachename), "%s/cache/%s", FS_Gamedir(), mod->name);
   FS_CreatePath(cachename);
   f = fopen (cachename, "rb");

   if (f)
   {   
      // read from cache
      ax = fread(&smooth, 1, sizeof(smooth), f);

      if(ax==sizeof(smooth))
      {
         unsigned   ang;
         if(fread(&ang, 1, sizeof(unsigned), f)!=sizeof(unsigned)) goto badd;
         if (ang != (unsigned)(cos(DEG2RAD(45))*0x7fffffff))
         {
badd:         fclose(f);
            goto bad;
         }
         cache = true;
            
         cx = pheader->num_xyz * pheader->num_frames * sizeof(byte);
         mod->binormals = binormals =(byte*)Hunk_Alloc (cx);
         mod->tangents = tangents = (byte*)Hunk_Alloc (cx);
         mod->memorySize += cx;
         mod->memorySize += cx;
         if(fread(&cs_binormals, 1, sizeof(int), f)!=sizeof(int)) goto badd;
         ax = fread(mod->binormals, 1, cx, f);
         if(ax==cx)
         {
            if(fread(&cs_tangents, 1, sizeof(int), f)!=sizeof(int))   goto badd;
            ax = fread(mod->tangents, 1, cx, f);
            success = (ax==cx);
            if(success) {
               goto ok;
            }
         }               
      }
      fclose(f);
   }
   
bad:
   Com_Printf("^1%s: invalid cache\n", mod->name);
   success = false;
ok:
   if(success)
   {
      checksum = LittleLong (Com_BlockChecksum (mod->binormals, cx));

      if(checksum == cs_binormals)
      {
         checksum = LittleLong (Com_BlockChecksum (mod->tangents, cx));
         if(checksum == cs_tangents){
               goto okey;
         }
      }
      Com_Printf("^1%s: invalid checksum!\n", mod->name);
      success = false;
   }

   if(success)
   {
okey:   
      Com_DPrintf("%s: loaded from cache\n", mod->name);

      HACK_RecalcVertsLightNormalIdx(pheader);

      goto exit;
   }

   if (cache)
   {
      Com_DPrintf("error loading /%s from cache...\n", mod->name);
   }
   Com_Printf("^3%s: calculating extra data\n", mod->name);

   /* ==============
   cache not found - recalc it
   =============== */
   HACK_RecalcVertsLightNormalIdx(pheader);

   cx = pheader->num_xyz * pheader->num_frames * sizeof(byte);
      
   // Calculate tangents for vertices (bump mapping)      
   mod->binormals = binormals = (byte*)Hunk_Alloc (cx);
   mod->tangents = tangents = (byte*)Hunk_Alloc (cx);
   mod->memorySize += cx;
   mod->memorySize += cx;

   //for all frames
   for (i=0; i<pheader->num_frames; i++)
   {
      //set temp to zero
      memset(tangents_, 0, pheader->num_xyz*sizeof(vec3_t));
      memset(binormals_, 0, pheader->num_xyz*sizeof(vec3_t));

      frame = (daliasframe_t *)((byte *)pheader + pheader->ofs_frames + i * pheader->framesize);
      verts = frame->verts;

      //for all tris
      for (j=0; j<pheader->num_tris; j++)
      {
         vec3_t   vv0,vv1,vv2;
         vec3_t tangent, binormal;

         vv0[0] = (float)verts[tris[j].index_xyz[0]].v[0];
         vv0[1] = (float)verts[tris[j].index_xyz[0]].v[1];
         vv0[2] = (float)verts[tris[j].index_xyz[0]].v[2];
         vv1[0] = (float)verts[tris[j].index_xyz[1]].v[0];
         vv1[1] = (float)verts[tris[j].index_xyz[1]].v[1];
         vv1[2] = (float)verts[tris[j].index_xyz[1]].v[2];
         vv2[0] = (float)verts[tris[j].index_xyz[2]].v[0];
         vv2[1] = (float)verts[tris[j].index_xyz[2]].v[1];
         vv2[2] = (float)verts[tris[j].index_xyz[2]].v[2];

         VecsForTris(vv0, vv1, vv2,
                  &st[tris[j].index_st[0]].s,
                  &st[tris[j].index_st[1]].s,
                  &st[tris[j].index_st[2]].s,
                  tangent, binormal);         //for all vertices in the tri

         for (k=0; k<3; k++)
         {
            l = tris[j].index_xyz[k];
            VectorAdd(tangents_[l], tangent, tangents_[l]);
            VectorAdd(binormals_[l], binormal, binormals_[l]);
         }
      }

      /// Berserker:
      // В некоторых моделях изредка попадаются несколько точек, имеющие одинаковые координаты.
      // Для таких случаев объединяем их вектора (если угол между нормалями невелик (до 15 градусов)).
      for (j=0; j<pheader->num_xyz; j++)
      {
         for (k=j+1; k<pheader->num_xyz; k++)
         {
            if(verts[j].v[0] == verts[k].v[0] && verts[j].v[1] == verts[k].v[1] && verts[j].v[2] == verts[k].v[2])
            {
               float *jnormal = r_avertexnormals[verts[j].lightnormalindex];
               float *knormal = r_avertexnormals[verts[k].lightnormalindex];

               if(DotProduct(jnormal, knormal) >= cos(DEG2RAD(45)))      /// smooth_cosine = cos(N), при величине угла между нормалями менее чем N градусов, считаем, что это одна точка
               {
                  VectorAdd(tangents_[j], tangents_[k], tangents_[j]);
                  VectorCopy(tangents_[j], tangents_[k]);
                  VectorAdd(binormals_[j], binormals_[k], binormals_[j]);
                  VectorCopy(binormals_[j], binormals_[k]);
               }
            }
         }

         // normalize averages
         VectorNormalize(tangents_[j]);
         VectorNormalize(binormals_[j]);

         tangents[i * pheader->num_xyz + j] = CalcNormal2Index(tangents_[j]);
         binormals[i * pheader->num_xyz + j] = CalcNormal2Index(binormals_[j]);
      }
   }
   
   // write cache to disk
   Q_sprintf (cachename, sizeof(cachename), "%s/cache/%s", FS_Gamedir(), mod->name);
   FS_CreatePath(cachename);
   f = fopen (cachename, "wb");

   if(f)
   {
      unsigned   sc;
      fwrite(&smooth, 1, sizeof(smooth), f);
      sc = (unsigned)(cos(DEG2RAD(45))*0x7fffffff);
      fwrite(&sc, 1, sizeof(unsigned), f);
      
      checksum = LittleLong (Com_BlockChecksum (binormals, cx));
      fwrite(&checksum, 1, sizeof(int), f);
      fwrite(binormals, 1, cx, f);

      checksum = LittleLong (Com_BlockChecksum (tangents, cx));
      fwrite(&checksum, 1, sizeof(int), f);
      fwrite(tangents, 1, cx, f);

      fclose(f);
   }
exit:   
   // Load the Md2 Indices
   Mod_LoadMd2Indices (mod, pheader);

   ClearBounds(mod->mins, mod->maxs);
   VectorClear(mod->center);
   frame = (daliasframe_t *)((byte *)pheader + pheader->ofs_frames);/// + i * pheader->framesize);      Берем только нулевой кадр!
   verts = frame->verts;

   for (k=0; k<pheader->num_xyz; k++)
   {
      for (l=0; l<3; l++)
      {
         if (mod->mins[l] > verts[k].v[l])   mod->mins[l] = verts[k].v[l];
         if (mod->maxs[l] < verts[k].v[l])   mod->maxs[l] = verts[k].v[l];
      }
   }

   for (l=0; l<3; l++)
   {
      mod->mins[l] = mod->mins[l] * frame->scale[l] + frame->translate[l];
      mod->maxs[l] = mod->maxs[l] * frame->scale[l] + frame->translate[l];
      mod->center[l] = (mod->mins[l] + mod->maxs[l]) * 0.5;
   }
   tempr[0] = mod->maxs[0] - mod->mins[0];
   tempr[1] = mod->maxs[1] - mod->mins[1];
   tempr[2] = 0;
   tempv[0] = 0;
   tempv[1] = 0;
   tempv[2] = mod->maxs[2] - mod->mins[2];
   mod->radius = max(VectorLength(tempr), VectorLength(tempv));

   for(i=0; i<3; i++)
   {
      mod->center[i] = (mod->maxs[i] + mod->mins[i]) * 0.5;
   }
}
Back to top
View user's profile Send private message
LordHavoc



Joined: 05 Nov 2004
Posts: 243
Location: western Oregon, USA

PostPosted: Fri Apr 02, 2010 2:13 pm    Post subject: Reply with quote

I do not see any relation between model loading and lightmap ambient occlusion.
Back to top
View user's profile Send private message Visit poster's website
reckless



Joined: 24 Jan 2008
Posts: 390
Location: inside tha debugger

PostPosted: Fri Apr 02, 2010 10:54 pm    Post subject: Reply with quote

ups wrong code section Embarassed

was this one

Code:
void Mod_LoadFaces(lump_t * l)
{
#define MAGIC_CACHE 1237
   dface_t      *in;
   msurface_t   *out;
   int         i, count, surfnum;
   int         planenum, side;
   int         ti;
   byte      *cache = NULL;
   char      cachename[MAX_QPATH];
   int         ci, cj, flp;
   float      *vi, *vj;
   msurface_t   *si, *sj;
   vec3_t      ni, nj, ttt, tttt, ttttt, vector;
   FILE      *f = NULL;
   unsigned   sc = (unsigned)(cos(DEG2RAD(45))*0x7fffffff);
   int         j;
   int         offs = 0;
   unsigned   chk = LittleLong (Com_BlockChecksum (mod_base, mod_filelen));
   qboolean   caching__ = false;
   unsigned   checksum;
   qboolean   caching_calc = false;
   
   in = (void *) (mod_base + l->fileofs);

   if (l->filelen % sizeof(*in)) {
      VID_Error(ERR_DROP, "MOD_LoadBmodel: funny lump size in %s", loadmodel->name);
   }
   count = l->filelen / sizeof(*in);
   out = Hunk_Alloc(count * sizeof(*out));
   
   loadmodel->surfaces = out;
   loadmodel->numsurfaces = count;   
   loadmodel->memorySize += count * sizeof(*out);

   currentmodel = loadmodel;

   GL_BeginBuildingLightmaps(loadmodel);

   for ( surfnum=0 ; surfnum<count ; surfnum++, in++, out++) {
      out->firstedge = LittleLong(in->firstedge);
      out->numedges = LittleShort(in->numedges);      
      out->flags = 0;
      out->polys = NULL;

      planenum = LittleShort(in->planenum);
      side = LittleShort(in->side);

      if (side) {
         out->flags |= SURF_PLANEBACK;         
      }
      out->plane = loadmodel->planes + planenum;

      ti = LittleShort (in->texinfo);

      if (ti < 0 || ti >= loadmodel->numtexinfo) {
         Sys_Error ("MOD_LoadBmodel: bad texinfo number");
      }
      out->texinfo = loadmodel->texinfo + ti;

      CalcSurfaceExtents (out);
            
      // lighting info
      for (i=0 ; i<MAXLIGHTMAPS ; i++) {
         out->styles[i] = in->styles[i];
      }
      i = LittleLong(in->lightofs);

      if (i == -1) {
         out->samples = NULL;
      } else {
         out->samples = loadmodel->lightdata + i;
      }

      // set the drawing flags
      if (out->texinfo->flags & SURF_WARP) {
         out->flags |= SURF_DRAWTURB;
         for (i=0 ; i<2 ; i++) {
            out->extents[i] = 16384;
            out->texturemins[i] = -8192;
         }
         GL_SubdivideSurface (out);   // cut up polygon for warps
      }

      // create lightmaps and polygons
      if (!(out->texinfo->flags & (SURF_SKY|SURF_TRANS33|SURF_TRANS66|SURF_WARP))) {
         GL_CreateSurfaceLightmap (out);
      }

      if (!(out->texinfo->flags & SURF_WARP)) {
         GL_BuildPolygonFromSurface(out);      
         GL_AddFlareSurface(out);         
      }

      // pick up some pvs info.
      // someone needs to be shot here btw go figure.
      CalcSurfaceBounds(out);
   }

   // Calc Tangent space
   // create the cache directory
   Q_sprintf (cachename, sizeof(cachename), "%s/cache/%s", FS_Gamedir(), loadmodel->name);

   FS_CreatePath(cachename);

   f = fopen (cachename, "rb");

   if (f) {

      // read from cache
      unsigned   ang;
      unsigned   check;
      unsigned   check_from_cache;

      flp = FS_filelength2(f) - sizeof(float) - sizeof(unsigned) - sizeof(float);
      
      if (flp < 0) goto bad;
      if(fread(&ang, 1, sizeof(unsigned), f) != sizeof(unsigned)) goto bad;
      if (ang != (unsigned)( cos(DEG2RAD(45)) * 0x7fffffff)) goto bad;
      if(fread(&check_from_cache, 1, sizeof(unsigned), f) != sizeof(unsigned)) goto bad;
      if (check_from_cache != chk) goto bad;
      cache = (byte*)malloc(flp);
      fread(&check, 1, sizeof(unsigned), f);
      check += MAGIC_CACHE;
      fread(cache, 1, flp, f);
      checksum = LittleLong (Com_BlockChecksum (cache, flp));

      if (checksum == check) {

         flp = 0;

         for (i=0 ; i<count ; i++) {

            si = &currentmodel->surfaces[i];

            if (!(si->texinfo->flags & (SURF_SKY|SURF_TRANS33|SURF_TRANS66|SURF_NODRAW))) {
               for (ci=0, vi = si->polys->verts[0]; ci<si->numedges; ci++, vi+=VERTEXSIZE)   {
                  vi[7] = r_avertexnormals[cache[flp]][0];
                  vi[8] = r_avertexnormals[cache[flp]][1];
                  vi[9] = r_avertexnormals[cache[flp++]][2];
                  vi[10] = r_avertexnormals[cache[flp]][0];
                  vi[11] = r_avertexnormals[cache[flp]][1];
                  vi[12] = r_avertexnormals[cache[flp++]][2];
                  vi[13] = r_avertexnormals[cache[flp]][0];
                  vi[14] = r_avertexnormals[cache[flp]][1];
                  vi[15] = r_avertexnormals[cache[flp++]][2];
               }
            }
         }
         free (cache);
         fclose (f);
      } else {
         free (cache);
bad:      
         fclose (f);
         Com_Printf("^3 Invalid cache\n");
         goto crea;
      }
   } else {
crea:   
      if (!caching__) {
         Com_Printf("^3Calculating extra data\n");
      } else {
         caching_calc = true;
      }
      f = fopen (cachename, "wb");

      flp = 0;

      for (i=0 ; i<count ; i++) {

         si = &currentmodel->surfaces[i];

         if (!(si->texinfo->flags & (SURF_SKY|SURF_TRANS33|SURF_TRANS66|SURF_NODRAW))) {

            vi = si->polys->verts[0];

            for (ci=0; ci<si->numedges; ci++, vi+=VERTEXSIZE) {
               vi[7] = vi[8] = vi[9] = vi[10] = vi[11] = vi[12] = vi[13] = vi[14] = vi[15] = 0;
            }

            if (si->flags & SURF_PLANEBACK)   {
               VectorNegate(si->plane->normal, ni);
            } else {
               VectorCopy(si->plane->normal, ni);
            }

            for (j=0 ; j<count ; j++) {

               sj = &currentmodel->surfaces[j];

               if (!(sj->texinfo->flags & (SURF_SKY|SURF_TRANS33|SURF_TRANS66|SURF_NODRAW))) {
                  if (sj->flags & SURF_PLANEBACK) {
                     VectorNegate(sj->plane->normal, nj);
                  } else {
                     VectorCopy(sj->plane->normal, nj);
                  }

                  if(DotProduct(ni, nj) >= cos(DEG2RAD(45)) ) {

                     vi = si->polys->verts[0];

                     for (ci=0; ci<si->numedges; ci++, vi+=VERTEXSIZE) {

                        vj = sj->polys->verts[0];

                        for (cj=0; cj<sj->numedges; cj++, vj+=VERTEXSIZE) {
                           if (VectorCompare(vi, vj)) {
                              vi[7] += nj[0];
                              vi[8] += nj[1];
                              vi[9] += nj[2];
                           }
                        }
                     }
                  }
               }
            }
            vi = si->polys->verts[0];

            for (ci=0; ci<si->numedges; ci++, vi+=VERTEXSIZE) {

               VectorSet(ttt, vi[7], vi[8], vi[9]);
               VectorNormalize(ttt);

               if(DotProduct(ttt, ni)<cos(DEG2RAD(45))) {
                  vi[7] = ttt[0] = ni[0];
                  vi[8] = ttt[1] = ni[1];
                  vi[9] = ttt[2] = ni[2];
               } else {
                  vi[7] = ttt[0];
                  vi[8] = ttt[1];
                  vi[9] = ttt[2];
               }
               CrossProduct(ttt, si->texinfo->vecs[0], tttt);
               CrossProduct(ttt, tttt, ttttt);
               VectorNormalize(ttttt);

               if (DotProduct(ttttt, si->texinfo->vecs[0]) < 0) {
                  vi[10] = -ttttt[0];
                  vi[11] = -ttttt[1];
                  vi[12] = -ttttt[2];
               } else {
                  vi[10] = ttttt[0];
                  vi[11] = ttttt[1];
                  vi[12] = ttttt[2];
               }
               CrossProduct(ttt, si->texinfo->vecs[1], tttt);
               CrossProduct(ttt, tttt, ttttt);
               VectorNormalize(ttttt);

               if (DotProduct(ttttt, si->texinfo->vecs[1]) < 0) {
                  vi[13] = -ttttt[0];
                  vi[14] = -ttttt[1];
                  vi[15] = -ttttt[2];
               } else {
                  vi[13] = ttttt[0];
                  vi[14] = ttttt[1];
                  vi[15] = ttttt[2];
               }
               flp += 3;
            }
         }
      }

      // write to cache
      cache = (byte *)malloc(flp);

      for (i=0 ; i<count ; i++) {

         si = &currentmodel->surfaces[i];

         if (!(si->texinfo->flags & (SURF_SKY|SURF_TRANS33|SURF_TRANS66|SURF_NODRAW))) {
            for (ci=0, vi = si->polys->verts[0]; ci<si->numedges; ci++, vi+=VERTEXSIZE)   {
               vector[0] = vi[7];
               vector[1] = vi[8];
               vector[2] = vi[9];
               cache[offs++] = CalcNormal2Index(vector);
               vector[0] = vi[10];
               vector[1] = vi[11];
               vector[2] = vi[12];
               cache[offs++] = CalcNormal2Index(vector);
               vector[0] = vi[13];
               vector[1] = vi[14];
               vector[2] = vi[15];
               cache[offs++] = CalcNormal2Index(vector);
            }
         }
      }
      checksum = LittleLong (Com_BlockChecksum (cache, flp));
      
      fwrite(&sc, 1, sizeof(unsigned), f);
      fwrite(&chk, 1, sizeof(unsigned), f);
      checksum -= MAGIC_CACHE;
      fwrite(&checksum, 1, sizeof(unsigned), f);
      fwrite (cache, 1, flp, f);
      free(cache);
      fclose (f);
   }
   GL_EndBuildingLightmaps();
#undef MAGIC_CACHE
}


it does seem to be lightmap related allthough i cant tell if any of it is for ambient acclusion.

to me it looks like its storing the vertex values my guess is its used for normalmaps and such.
Back to top
View user's profile Send private message
LordHavoc



Joined: 05 Nov 2004
Posts: 243
Location: western Oregon, USA

PostPosted: Sat Apr 03, 2010 1:59 am    Post subject: Reply with quote

reckless wrote:
it does seem to be lightmap related allthough i cant tell if any of it is for ambient acclusion.

to me it looks like its storing the vertex values my guess is its used for normalmaps and such.


Also not related at all to ambient occlusion, but at least on the topic of lightmaps.

However no relevance to the discussion at hand.
Back to top
View user's profile Send private message Visit poster's website
reckless



Joined: 24 Jan 2008
Posts: 390
Location: inside tha debugger

PostPosted: Sat Apr 03, 2010 3:14 am    Post subject: Reply with quote

aye had a look at the code and theres a bit more to it.

just noticed you had the feature in dp and i remembered seing something similar in this but as turns out not exactly related.
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    Inside3d Forums Forum Index -> General Programming All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2004 phpBB Group