⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 normalmapper.cpp

📁 hl2 source code. Do not use it illegal.
💻 CPP
📖 第 1 页 / 共 5 页
字号:
//////////////////////////////////////////////////////////////////////////
void
ComputePlaneEqn (float v0[3], float v1[3], float norm[3], double plane[4])
{
   // Find A, B, C - normal to plane
   double v[3];
   VEC_Subtract (v1, v0, v);
   VEC_Cross (v, norm, plane);
   double tmp = sqrt (plane[0]*plane[0] + plane[1]*plane[1]+plane[2]*plane[2]);
   if (tmp < EPSILON)
   {
      plane[0] = 0;
      plane[1] = 0;
      plane[2] = 1;
   }
   else
   {
      plane[0] = plane[0]/tmp;
      plane[1] = plane[1]/tmp;
      plane[2] = plane[2]/tmp;
   }

   // Find D (A*x + B*y + C*z = D)
   plane[3] = VEC_DotProduct (plane, v0);
}

//////////////////////////////////////////////////////////////////////////
// Is the triangle "inside" the plane - if any of the three points lie on
// or above the given plane then the triangle is "inside". Given the
// plane equation above if the dot product with ABC is >= D it's in!
//////////////////////////////////////////////////////////////////////////
inline bool
IsInside (NmRawTriangle* tri, double plane[4])
{
   if (VEC_DotProduct (tri->vert[0].v, plane) >= plane[3])
   {
      return true;
   }
   if (VEC_DotProduct (tri->vert[1].v, plane) >= plane[3])
   {
      return true;
   }
   if (VEC_DotProduct (tri->vert[2].v, plane) >= plane[3])
   {
      return true;
   }
   return false;
}

//////////////////////////////////////////////////////////////////////////
// Convert to John style experimental pixel format
//////////////////////////////////////////////////////////////////////////
void
ConvertToJohn (double x, double y, double z, JohnPixel* jp)
{
   // Compute one minus z
   double omz = 1.0 - z;
   double ax = fabs (x);
   double ay = fabs (y);
   double aomz = fabs (omz);

   // Find max.
   double max;
   if (ax > ay)
   {
      if (ax > aomz)
      {
         max = ax;
      }
      else
      {
         max = aomz;
      }
   }
   else
   {
      if (ay > aomz)
      {
         max = ay;
      }
      else
      {
         max = aomz;
      }
   }

   // Now compute values.
   jp->r = PACKINTOBYTE_MINUS1TO1(x/max);
   jp->g = PACKINTOBYTE_MINUS1TO1(y/max);
   jp->b = PACKINTOBYTE_MINUS1TO1(omz/max);
   jp->a = PACKINTOBYTE_0TO1(max);
}

//////////////////////////////////////////////////////////////////////////
// Fetch from the normal map given the uv.
//////////////////////////////////////////////////////////////////////////
void
Fetch (float* map, int width, int height, double u, double v, double bumpN[3])
{
   // Get coordinates in 0-1 range
   if ((u < 0.0) || (u > 1.0))
   {
      u -= floor(u);
   }
   if ((v < 0.0) || (v > 1.0))
   {
      v -= floor(v);
   }

   // Now figure out the texel information for u coordinate
   double up = (double)(width-1) * u;
   double umin = floor (up);
   double umax = ceil (up);
   double ufrac = up - umin;

   // Now figure out the texel information for v coordinate
   double vp = (double)(height-1) * v;
   double vmin = floor (vp);
   double vmax = ceil (vp);
   double vfrac = vp - vmin;

   // First term umin/vmin
   int idx = (int)(vmin)*width*3 + (int)(umin)*3;
   bumpN[0] = ((1.0-ufrac)*(1.0-vfrac)*(double)(map[idx]));
   bumpN[1] = ((1.0-ufrac)*(1.0-vfrac)*(double)(map[idx+1]));
   bumpN[2] = ((1.0-ufrac)*(1.0-vfrac)*(double)(map[idx+2]));

   // Second term umax/vmin
   idx = (int)(vmin)*width*3 + (int)(umax)*3;
   bumpN[0] += (ufrac*(1.0-vfrac)*(double)(map[idx]));
   bumpN[1] += (ufrac*(1.0-vfrac)*(double)(map[idx+1]));
   bumpN[2] += (ufrac*(1.0-vfrac)*(double)(map[idx+2]));

   // Third term umin/vmax
   idx = (int)(vmax)*width*3 + (int)(umin)*3;
   bumpN[0] += ((1.0-ufrac)*vfrac*(double)(map[idx]));
   bumpN[1] += ((1.0-ufrac)*vfrac*(double)(map[idx+1]));
   bumpN[2] += ((1.0-ufrac)*vfrac*(double)(map[idx+2]));

   // Fourth term umax/vmax
   idx = (int)(vmax)*width*3 + (int)(umax)*3;
   bumpN[0] += (ufrac*vfrac*(double)(map[idx]));
   bumpN[1] += (ufrac*vfrac*(double)(map[idx+1]));
   bumpN[2] += (ufrac*vfrac*(double)(map[idx+2]));
}

//////////////////////////////////////////////////////////////////////////
// Get a pixel from the image.
//////////////////////////////////////////////////////////////////////////
inline void 
ReadPixel (BYTE* image, int width, int off, pixel* pix, int x, int y)
{
   int idx = y*width*off + x*off;
   if (off > 0)
   {
      pix->red = image[idx];
   }
   if (off > 1)
   {
      pix->blue = image[idx + 1];
   }
   if (off > 2)
   {
      pix->green = image[idx + 2];
   }
}

//////////////////////////////////////////////////////////////////////////
// Reads a height field file from disk and converts it into a normal for
// use in perturbing the normals generated from the high res model
//////////////////////////////////////////////////////////////////////////
void
GetBumpMapFromHeightMap (char* bumpName, int* bumpWidth,  int* bumpHeight,
                         float** bumpMap, float scale)
{
   // No height field
   if (bumpName == NULL)
   {
      (*bumpWidth) = 0;
      (*bumpHeight) = 0;
      (*bumpMap) = NULL;
      return;
   }

   // First read in the heightmap.
   FILE* fp = fopen (bumpName, "rb");
   if (fp == NULL)
   {
      NmPrint ("ERROR: Unable to open %s\n", bumpName);
      exit (-1);
   }
   BYTE* image;
   int bpp;
   if (!TGAReadImage (fp, bumpWidth, bumpHeight, &bpp, &image))
   {
      NmPrint ("ERROR: Unable to read %s\n", bumpName);
      exit (-1);
   }
   fclose (fp);

   // Allocate normal image.
   (*bumpMap) = new float [(*bumpWidth)*(*bumpHeight)*3];
   if ((*bumpMap) == NULL)
   {
      NmPrint ("ERROR: Unable to allocate normal map memory!");
      exit (-1);
   }
   
   // Get offset
   int off = 0;
   switch (bpp)
   {
      case 8:
         off = 1;
         break;
      case 16:
         off = 2;
         break;
      case 24:
         off = 3;
         break;
      case 32:
         off = 4;
         break;
      default:
         NmPrint ("ERROR: Unhandled bit depth for bump map!\n");
         exit (-1);
   }

   // Sobel the image to get normals.
   float dX, dY, nX, nY, nZ, oolen;
   pixel pix;
   for (int y = 0; y < (*bumpHeight); y++)
   {
      for (int x = 0; x < (*bumpWidth); x++)
      {
         // Do Y Sobel filter
         ReadPixel (image, (*bumpWidth), off,
                    &pix, (x-1+(*bumpWidth)) % (*bumpWidth), (y+1) % (*bumpHeight));
         dY  = ((((float) pix.red) / 255.0f)*scale) * -1.0f;
            
         ReadPixel(image, (*bumpWidth), off,
                   &pix,   x   % (*bumpWidth), (y+1) % (*bumpHeight));
         dY += ((((float) pix.red) / 255.0f)*scale) * -2.0f;
            
         ReadPixel(image, (*bumpWidth), off,
                   &pix, (x+1) % (*bumpWidth), (y+1) % (*bumpHeight));
         dY += ((((float) pix.red) / 255.0f)*scale) * -1.0f;
            
         ReadPixel(image, (*bumpWidth), off,
                   &pix, (x-1+(*bumpWidth)) % (*bumpWidth), (y-1+(*bumpHeight)) % (*bumpHeight));
         dY += ((((float) pix.red) / 255.0f)*scale) *  1.0f;
            
         ReadPixel(image, (*bumpWidth), off,
                   &pix,   x   % (*bumpWidth), (y-1+(*bumpHeight)) % (*bumpHeight));
         dY += ((((float) pix.red) / 255.0f)*scale) *  2.0f;
            
         ReadPixel(image, (*bumpWidth), off,
                   &pix, (x+1) % (*bumpWidth), (y-1+(*bumpHeight)) % (*bumpHeight));
         dY += ((((float) pix.red) / 255.0f)*scale) *  1.0f;
            
         // Do X Sobel filter
         ReadPixel(image, (*bumpWidth), off,
                   &pix, (x-1+(*bumpWidth)) % (*bumpWidth), (y-1+(*bumpHeight)) % (*bumpHeight));
         dX  = ((((float) pix.red) / 255.0f)*scale) * -1.0f;
            
         ReadPixel(image, (*bumpWidth), off,
                   &pix, (x-1+(*bumpWidth)) % (*bumpWidth),   y   % (*bumpHeight));
         dX += ((((float) pix.red) / 255.0f)*scale) * -2.0f;
            
         ReadPixel(image, (*bumpWidth), off,
                   &pix, (x-1+(*bumpWidth)) % (*bumpWidth), (y+1) % (*bumpHeight));
         dX += ((((float) pix.red) / 255.0f)*scale) * -1.0f;
            
         ReadPixel(image, (*bumpWidth), off,
                   &pix, (x+1) % (*bumpWidth), (y-1+(*bumpHeight)) % (*bumpHeight));
         dX += ((((float) pix.red) / 255.0f)*scale) *  1.0f;
            
         ReadPixel(image, (*bumpWidth), off,
                   &pix, (x+1) % (*bumpWidth),   y   % (*bumpHeight));
         dX += ((((float) pix.red) / 255.0f)*scale) *  2.0f;
            
         ReadPixel(image, (*bumpWidth), off,
                   &pix, (x+1) % (*bumpWidth), (y+1) % (*bumpHeight));
         dX += ((((float) pix.red) / 255.0f)*scale) *  1.0f;
            
            
         // Cross Product of components of gradient reduces to
         nX = -dX;
         nY = -dY;
         nZ = 1;
            
         // Normalize
         oolen = 1.0f/((float) sqrt(nX*nX + nY*nY + nZ*nZ));
         nX *= oolen;
         nY *= oolen;
         nZ *= oolen;

         int idx = y*(*bumpWidth)*3 + x*3;
         (*bumpMap)[idx] = nX;
         (*bumpMap)[idx+1] = nY;
         (*bumpMap)[idx+2] = nZ;
      }
   }
}

//////////////////////////////////////////////////////////////////////////
// Check argument flags and set the appropriate values.
//////////////////////////////////////////////////////////////////////////
void
TestArgs (char* args)
{
   // Print out flags
   NmPrint ("Flags: %s\n", args);

   // Super-sample number
   if (strstr (args, "1") != NULL)
   {
      gNumSamples = 1;
   }
   if (strstr (args, "2") != NULL)
   {
      gNumSamples = 2;
   }
   if (strstr (args, "3") != NULL)
   {
      gNumSamples = 3;
   }
   if (strstr (args, "4") != NULL)
   {
      gNumSamples = 4;
   }
   if (strstr (args, "5") != NULL)
   {
      gNumSamples = 5;
   }
   if (strstr (args, "6") != NULL)
   {
      gNumSamples = 9;
   }
   if (strstr (args, "7") != NULL)
   {
      gNumSamples = 13;
   }
   if (strstr (args, "8") != NULL)
   {
      gNumSamples = 21;
   }
   if (strstr (args, "9") != NULL)
   {
      gNumSamples = 37;
   }
   if (strstr (args, "0") != NULL)
   {
      gNumSamples = 57;
   }

   // Rulesets for determining best normals
   if (strstr (args, "c") != NULL)
   {
      gNormalRules = NORM_RULE_CLOSEST;
      if (strstr (args, "X") != NULL)
      {
         gNormalRules = NORM_RULE_FRONT_CLOSEST;
      }
   }
   if (strstr (args, "C") != NULL)
   {
      gNormalRules = NORM_RULE_BEST_CLOSEST;
      if (strstr (args, "X") != NULL)
      {
         gNormalRules = NORM_RULE_FRONT_BEST_CLOSEST;
      }
   }
   if (strstr (args, "f") != NULL)
   {
      gNormalRules = NORM_RULE_FARTHEST;
      if (strstr (args, "X") != NULL)
      {
         gNormalRules = NORM_RULE_FRONT_FURTHEST;
      }
   }
   if (strstr (args, "F") != NULL)
   {
      gNormalRules = NORM_RULE_BEST_FARTHEST;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -