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

📄 normalmapper.cpp

📁 hl2 source code. Do not use it illegal.
💻 CPP
📖 第 1 页 / 共 5 页
字号:
            {
               loBbox[k] = lowTris[i].vert[j].v[k];
            }
            if (lowTris[i].vert[j].v[k] > loBbox[k + 3])
            {
               loBbox[k + 3] = lowTris[i].vert[j].v[k];
            }
         }

         // Check texture coordinates
         if ((lowTris[i].texCoord[j].u < 0.0) ||
             (lowTris[i].texCoord[j].u > 1.0))
         {
            if (fabs(lowTris[i].texCoord[j].u) > EPSILON)
            {
               NmPrint ("ERROR: Texture coordinates must lie in the 0.0 - 1.0 range for the low res model (u: %f)!\n", lowTris[i].texCoord[j].u);
               exit (-1);
            }
            else
            {
               lowTris[i].texCoord[j].u = 0.0;
            }
         }
         if ((lowTris[i].texCoord[j].v < 0.0) ||
             (lowTris[i].texCoord[j].v > 1.0))
         {
            if (fabs(lowTris[i].texCoord[j].v) > EPSILON)
            {
               NmPrint ("ERROR: Texture coordinates must lie in the 0.0 - 1.0 range for the low res model! (v %f)\n", lowTris[i].texCoord[j].v);
               exit (-1);
            }
            else
            {
               lowTris[i].texCoord[j].v = 0.0;
            }
            
         }
      }
   }
   NmPrint ("Low poly bounding box: (%10.3f %10.3f %10.3f)\n", loBbox[0],
           loBbox[1], loBbox[2]);
   NmPrint ("                       (%10.3f %10.3f %10.3f)\n", loBbox[3],
            loBbox[4], loBbox[5]);

   // If the flag is set compute tangent space for all the low res triangles.
   NmTangentMatrix* tangentSpace = NULL;
   if (gInTangentSpace == true)
   {
      // Get tangent space.
      NmPrint ("Computing tangents\n");
      NmRawTangentSpaceD* tan = NULL;
      if (NmComputeTangentsD (lowNumTris, lowTris, &tan) == false)
      {
         NmPrint ("ERROR: Unable to compute tangent space!\n");
         exit (-1);
      }
      
      // Create tangent matrices
      tangentSpace = new NmTangentMatrix [lowNumTris];
      for (int j = 0; j < lowNumTris; j++)
      {
         for (int k = 0; k < 3; k++)
         {
            tangentSpace[j].m[k][0] = tan[j].tangent[k].x;
            tangentSpace[j].m[k][3] = tan[j].tangent[k].y;
            tangentSpace[j].m[k][6] = tan[j].tangent[k].z;

            tangentSpace[j].m[k][1] = tan[j].binormal[k].x;
            tangentSpace[j].m[k][4] = tan[j].binormal[k].y;
            tangentSpace[j].m[k][7] = tan[j].binormal[k].z;

            tangentSpace[j].m[k][2] = lowTris[j].norm[k].x;
            tangentSpace[j].m[k][5] = lowTris[j].norm[k].y;
            tangentSpace[j].m[k][8] = lowTris[j].norm[k].z;
         }
      }
      delete [] tan;
   } // end if we need to deal with tangent space

   // Read in the high res model
//   fp = fopen (highName, "rb");
   fp = fopen (highName, "r");
   if (fp == NULL)
   {
      NmPrint ("ERROR: Unable to open %s\n", highName);
      exit (-1);
   }
   int highNumTris;
   NmRawTriangle* highTris;
//   if (NmReadTriangles (fp, &highNumTris, &highTris) == false)
   if (SMDReadTriangles (fp, &highNumTris, &highTris) == false)
   {
      NmPrint ("ERROR: Unable to read %s\n", highName);
      fclose (fp);
      exit (-1);
   }
   fclose (fp);
   NmPrint ("Found %d triangles in high res model\n", highNumTris);

   // Get high res bounding box.
   double hiBbox[6];
   hiBbox[0] = FLT_MAX; // X min
   hiBbox[1] = FLT_MAX; // Y min
   hiBbox[2] = FLT_MAX; // Z min
   hiBbox[3] = -FLT_MAX; // X max
   hiBbox[4] = -FLT_MAX; // Y max
   hiBbox[5] = -FLT_MAX; // Z max
   for (int h = 0; h < highNumTris; h++)
   {
      for (int j = 0; j < 3; j++)
      {
         for (int k = 0; k < 3; k++)
         {
            if (highTris[h].vert[j].v[k] < hiBbox[k])
            {
               hiBbox[k] = highTris[h].vert[j].v[k];
            }
            if (highTris[h].vert[j].v[k] > hiBbox[k + 3])
            {
               hiBbox[k + 3] = highTris[h].vert[j].v[k];
            }
         }
      }
   }
   NmPrint ("High poly bounding box: (%10.3f %10.3f %10.3f)\n", hiBbox[0],
            hiBbox[1], hiBbox[2]);
   NmPrint ("                        (%10.3f %10.3f %10.3f)\n", hiBbox[3],
            hiBbox[4], hiBbox[5]);

   // Tangents for high res if we need them.
   NmTangentMatrix* hTangentSpace = NULL;
   if (bumpName != NULL)
   {
      // Get tangent space.
      NmPrint ("Computing tangents\n");
      NmRawTangentSpaceD* tan = NULL;
      if (NmComputeTangentsD (highNumTris, highTris, &tan) == false)
      {
         NmPrint ("ERROR: Unable to compute tangent space!\n");
         exit (-1);
      }
      
      // Create tangent matrices
      hTangentSpace = new NmTangentMatrix [highNumTris];
      for (int j = 0; j < highNumTris; j++)
      {
         for (int k = 0; k < 3; k++)
         {
            hTangentSpace[j].m[k][0] = tan[j].tangent[k].x;
            hTangentSpace[j].m[k][3] = tan[j].tangent[k].y;
            hTangentSpace[j].m[k][6] = tan[j].tangent[k].z;

            hTangentSpace[j].m[k][1] = tan[j].binormal[k].x;
            hTangentSpace[j].m[k][4] = tan[j].binormal[k].y;
            hTangentSpace[j].m[k][7] = tan[j].binormal[k].z;

            hTangentSpace[j].m[k][2] = highTris[j].norm[k].x;
            hTangentSpace[j].m[k][5] = highTris[j].norm[k].y;
            hTangentSpace[j].m[k][8] = highTris[j].norm[k].z;
         }
      }
      delete [] tan;
   }
   
   // Loop over low res triangles and figure out which triangles in the
   // high res model are relevant for normal finding.
   NmVisible* visible = new NmVisible [lowNumTris];
   if (visible == NULL)
   {
      NmPrint ("ERROR: Unable to allocate visibility sets\n");
      exit (-1);
   }
   NmPrint ("Finding visible triangle sets\n");
   printf ("  0%%");
   for (int t = 0; t < lowNumTris; t++)
   {
      // Show some progress
      int progress = (int)(((float)(t)/(float)(lowNumTris))*100.0);
      char prog[24];
      sprintf (prog, "%3d%% ", progress);
      printf ("\r%s", prog);

      // Save off a pointer to the triangle and create
      NmRawTriangle* lTri = &lowTris[t];

      // Clear out the counts and allocate a new index
      visible[t].numTris = 0;
      visible[t].index = new unsigned int [highNumTris];
      if (visible[t].index == NULL)
      {
         NmPrint ("ERROR: Unable to allocate visibilty index.\n");
         exit (-1);
      }

      // Plane equation constants
      double plane[6][4];
      ComputePlaneEqn (lTri->vert[1].v, lTri->vert[0].v, lTri->norm[0].v,
                       plane[0]);
      ComputePlaneEqn (lTri->vert[1].v, lTri->vert[0].v, lTri->norm[1].v,
                       plane[1]);
      ComputePlaneEqn (lTri->vert[2].v, lTri->vert[1].v, lTri->norm[1].v,
                       plane[2]);
      ComputePlaneEqn (lTri->vert[2].v, lTri->vert[1].v, lTri->norm[2].v,
                       plane[3]);
      ComputePlaneEqn (lTri->vert[0].v, lTri->vert[2].v, lTri->norm[2].v,
                       plane[4]);
      ComputePlaneEqn (lTri->vert[0].v, lTri->vert[2].v, lTri->norm[0].v,
                       plane[5]);
      
      // Loop through the high res triangles to see if they are "visible"
      for (int h = 0; h < highNumTris; h++)
      {
         // Save off triangle pointer
         NmRawTriangle* hTri = &highTris[h];
         // Check to see if this triangle is in the planes defined by the
         // planes computed for the low res triangle
         if ( (IsInside (hTri, plane[0]) || IsInside (hTri, plane[1])) &&
              (IsInside (hTri, plane[2]) || IsInside (hTri, plane[3])) &&
              (IsInside (hTri, plane[4]) || IsInside (hTri, plane[5])) )
         {
            visible[t].index[visible[t].numTris] = (unsigned)h;
            visible[t].numTris++;
         }
      } // end for high res triangles
   } // end for low res triangles
   printf ("\r100%%\r");
   
   // Print some stats
   float sum = 0;
   for (int lt = 0; lt < lowNumTris; lt++)
   {
      sum += (float)(visible[lt].numTris);
   }
   if ((int)sum < 1)
   {
      NmPrint ("ERROR: No visible triangles found!\n");
      exit (-1);
   }
   NmPrint ("%6.1f avg visible/triangle\n", (float)(sum)/(float)(lowNumTris));
   
   // Create image and clear to a biased 0 so any untouched pixels won't
   // have a normal associated with them.
   float* img = new float[gWidth*gHeight*4];
   if (img == NULL)
   {
      NmPrint ("ERROR: Unable to allocate texture\n");
      exit (-1);
   }
   float* img2 = new float[gWidth*gHeight*4];
   if (img2 == NULL)
   {
      NmPrint ("ERROR: Unable to allocate texture\n");
      exit (-1);
   }

   // Get samples for supersampling
   Sample* samples = GetSamples (gNumSamples);

   // loop over mip levels
   int mipCount = 0;
   int lastWidth = gWidth;
   int lastHeight = gHeight;
   while ((gWidth > 0) && (gHeight > 0))
   {
      // A little info
      NmPrint ("Output normal map %d by %d\n", gWidth, gHeight);

      // If this is the first time, or we are recomputing each mip level
      // find the normals by ray casting.
      if ((gComputeMipLevels == MIP_RECOMPUTE) || (mipCount == 0))
      {
         // Zero out memory
         memset (img, 0, sizeof (float)*gWidth*gHeight*3);
         
         // Loop over the triangles in the low res model and rasterize them
         // into the normal texture based on the texture coordinates.
         NmPrint ("Computing normals\n");
         printf ("  0%%");
         NmEdge edge[3];
         NmEdge tmp;
         for (int l = 0; l < lowNumTris; l++)
         {
            // Show some progress
            int progress = (int)(((float)(l)/(float)(lowNumTris))*100.0);
            char prog[24];
            sprintf (prog, "%3d%% ", progress);
            printf ("\r%s", prog);
            
            // Save off a pointer to the triangle and create
            NmRawTriangle* lTri = &lowTris[l];
            
            // Find edges and sort by minimum Y
            GetEdge (&edge[0], lTri, 0, 1);
            GetEdge (&edge[1], lTri, 0, 2);
            GetEdge (&edge[2], lTri, 1, 2);
            if (edge[2].yMin < edge[1].yMin)
            {
               memcpy (&tmp, &edge[1], sizeof (NmEdge));
               memcpy (&edge[1], &edge[2], sizeof (NmEdge));
               memcpy (&edge[2], &tmp, sizeof (NmEdge));
            }
            if (edge[1].yMin < edge[0].yMin)
            {
               memcpy (&tmp, &edge[0], sizeof (NmEdge));
               memcpy (&edge[0], &edge[1], sizeof (NmEdge));
               memcpy (&edge[1], &tmp, sizeof (NmEdge));
            }
            
            // Find initial Barycentric parameter. Algorithm described at: 
            // http://research.microsoft.com/~hollasch/cgindex/math/barycentric.html
#if 0
            double x1 = lTri->texCoord[0].u * (gWidth-1);
            double x2 = lTri->texCoord[1].u * (gWidth-1);
            double x3 = lTri->texCoord[2].u * (gWidth-1);
            double y1 = lTri->texCoord[0].v * (gHeight-1);
            double y2 = lTri->texCoord[1].v * (gHeight-1);
            double y3 = lTri->texCoord[2].v * (gHeight-1);
#else
            double x1 = (float)INT_ROUND_TEXCOORD_U(lTri->texCoord[0].u);
            double x2 = (float)INT_ROUND_TEXCOORD_U(lTri->texCoord[1].u);
            double x3 = (float)INT_ROUND_TEXCOORD_U(lTri->texCoord[2].u);
            double y1 = (float)INT_ROUND_TEXCOORD_V(lTri->texCoord[0].v);
            double y2 = (float)INT_ROUND_TEXCOORD_V(lTri->texCoord[1].v);
            double y3 = (float)INT_ROUND_TEXCOORD_V(lTri->texCoord[2].v);
#endif
            double b0 = ((x2 - x1) * (y3 - y1) - (x3 - x1) * (y2 - y1)); 
            
            // Find min/max Y
            int minY = edge[0].yMin;
            int maxY = edge[0].yMax;
            if (edge[1].yMax > maxY)
            {
               maxY = edge[1].yMax;
            }
            if (edge[2].yMax > maxY)
            {
               maxY = edge[2].yMax;
            }
            
            // Now loop over Ys doing each "scanline"
            for (int y = minY; y <= maxY; y++)
            {
               // Find min and max X for this scanline. 
               // I'm sure there's a smarter way to do this.
               int minX = 32767;
               int maxX = 0;
               for (int e = 0; e < 3; e++)
               {
                  // See if this edge is active.
                  if ((edge[e].yMin <= y) && (edge[e].yMax >= y))
                  {
                     // Check it's X values to see if they are min or max.
                     if (edge[e].x < minX)
                     {
                        minX = edge[e].x;
                     }
                     if (edge[e].x > maxX)
                     {
                        maxX = edge[e].x;
                     }
                     
                     // update x for next scanline
                     edge[e].increment += edge[e].numerator;
                     if (edge[e].denominator != 0)
                     {
                        if (edge[e].numerator < 0)
                        {
                           while (edge[e].increment <= 0)
                           {
                              edge[e].x--;
                              edge[e].increment += edge[e].denominator;
                           }
                        }
                        else
                        {
                           while (edge[e].increment > edge[e].denominator)
                           {
                              edge[e].x++;
                              edge[e].increment -= edge[e].denominator;
                           }
                        }
                     }
                  } // end if edge is active
               } // end for number of edges

⌨️ 快捷键说明

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