LCOV - code coverage report
Current view: top level - source/third_party/mikktspace - weldmesh.cpp (source / functions) Hit Total Coverage
Test: 0 A.D. test coverage report Lines: 1 84 1.2 %
Date: 2023-01-19 00:18:29 Functions: 2 4 50.0 %

          Line data    Source code
       1             : // Slightly modified version of weldmesh, by Wildfire Games, for 0 A.D.
       2             : // 
       3             : // Motivation for changes:
       4             : //  * Fix build on *BSD (including malloc.h produces an error)
       5             : 
       6             : #include "precompiled.h"
       7             : 
       8             : #ifdef _MSC_VER
       9             : # pragma warning(disable:4456) // hides previous local declaration
      10             : #endif
      11             : 
      12             : /**
      13             :  *  Copyright (C) 2011 by Morten S. Mikkelsen
      14             :  *
      15             :  *  This software is provided 'as-is', without any express or implied
      16             :  *  warranty.  In no event will the authors be held liable for any damages
      17             :  *  arising from the use of this software.
      18             :  *
      19             :  *  Permission is granted to anyone to use this software for any purpose,
      20             :  *  including commercial applications, and to alter it and redistribute it
      21             :  *  freely, subject to the following restrictions:
      22             :  *
      23             :  *  1. The origin of this software must not be misrepresented; you must not
      24             :  *     claim that you wrote the original software. If you use this software
      25             :  *     in a product, an acknowledgment in the product documentation would be
      26             :  *     appreciated but is not required.
      27             :  *  2. Altered source versions must be plainly marked as such, and must not be
      28             :  *     misrepresented as being the original software.
      29             :  *  3. This notice may not be removed or altered from any source distribution.
      30             :  */
      31             : 
      32             : 
      33             : #include "weldmesh.h"
      34             : #include <string.h>
      35             : #include <assert.h>
      36             : 
      37             : #if defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__)
      38             : #include <stdlib.h>  /* BSD-based OSes get their malloc stuff through here */
      39             : #else
      40             : #include <malloc.h> 
      41             : #endif
      42             : 
      43             : static void MergeVertsFast(int * piCurNrUniqueVertices, int * piRemapTable, float * pfVertexDataOut, int * piVertexIDs,
      44             :               const float pfVertexDataIn[], const int iNrVerticesIn, const int iFloatsPerVert,
      45             :               const int iL_in, const int iR_in, const int iChannelNum);
      46             : 
      47           0 : int WeldMesh(int * piRemapTable, float * pfVertexDataOut,
      48             :               const float pfVertexDataIn[], const int iNrVerticesIn, const int iFloatsPerVert)
      49             : {
      50           0 :     int iUniqueVertices = 0, i=0;
      51           0 :     int * piVertexIDs = NULL;
      52           0 :     if(iNrVerticesIn<=0) return 0;
      53             : 
      54             : 
      55           0 :     iUniqueVertices = 0;
      56           0 :     piVertexIDs = (int *) malloc(sizeof(int)*iNrVerticesIn);
      57           0 :     if(piVertexIDs!=NULL)
      58             :     {
      59           0 :         for(i=0; i<iNrVerticesIn; i++)
      60             :         {
      61           0 :             piRemapTable[i] = -1;
      62           0 :             piVertexIDs[i] = i;
      63             :         }
      64             : 
      65           0 :         MergeVertsFast(&iUniqueVertices, piRemapTable, pfVertexDataOut, piVertexIDs,
      66             :                                          pfVertexDataIn, iNrVerticesIn, iFloatsPerVert, 0, iNrVerticesIn-1, 0);
      67             : 
      68           0 :         free(piVertexIDs);
      69             : 
      70             :         // debug check
      71           0 :         for(i=0; i<iUniqueVertices; i++)
      72           0 :             assert(piRemapTable[i]>=0);
      73             :     }
      74             : 
      75           0 :     return iUniqueVertices;
      76             : }
      77             : 
      78             : 
      79             : 
      80             : 
      81             : 
      82           0 : static void MergeVertsFast(int * piCurNrUniqueVertices, int * piRemapTable, float * pfVertexDataOut, int * piVertexIDs,
      83             :               const float pfVertexDataIn[], const int iNrVerticesIn, const int iFloatsPerVert,
      84             :               const int iL_in, const int iR_in, const int iChannelNum)
      85             : {
      86           0 :     const int iCount = iR_in-iL_in+1;
      87           0 :     int l=0;
      88             :     float fMin, fMax, fAvg;
      89           0 :     assert(iCount>0);
      90             :     // make bbox
      91           0 :     fMin = pfVertexDataIn[ piVertexIDs[iL_in]*iFloatsPerVert + iChannelNum]; fMax = fMin;
      92           0 :     for(l=(iL_in+1); l<=iR_in; l++)
      93             :     {
      94           0 :         const int index = piVertexIDs[l]*iFloatsPerVert + iChannelNum;
      95           0 :         const float fVal = pfVertexDataIn[index];
      96           0 :         if(fMin>fVal) fMin=fVal;
      97           0 :         else if(fMax<fVal) fMax=fVal;
      98             :     }
      99             : 
     100             :     // terminate recursion when the separation/average value
     101             :     // is no longer strictly between fMin and fMax values.
     102           0 :     fAvg = 0.5f*(fMax + fMin);
     103           0 :     if(fAvg<=fMin || fAvg>=fMax || iCount==1)
     104             :     {
     105           0 :         if((iChannelNum+1) == iFloatsPerVert || iCount==1)  // we are done, weld by hand
     106             :         {
     107           0 :             int iUniqueNewVertices = 0;
     108           0 :             float * pfNewUniVertsOut = &pfVertexDataOut[ piCurNrUniqueVertices[0]*iFloatsPerVert ];
     109             : 
     110           0 :             for(l=iL_in; l<=iR_in; l++)
     111             :             {
     112           0 :                 const int index = piVertexIDs[l]*iFloatsPerVert;
     113             : 
     114           0 :                 int iFound = 0; // didn't find copy yet.
     115           0 :                 int l2=0;
     116           0 :                 while(l2<iUniqueNewVertices && iFound==0)
     117             :                 {
     118           0 :                     const int index2 = l2*iFloatsPerVert;
     119             : 
     120           0 :                     int iAllSame = 1;
     121           0 :                     int c=0;
     122           0 :                     while(iAllSame!=0 && c<iFloatsPerVert)
     123             :                     {
     124           0 :                         iAllSame &= (pfVertexDataIn[index+c] == pfNewUniVertsOut[index2+c] ? 1 : 0);
     125           0 :                         ++c;
     126             :                     }
     127             : 
     128           0 :                     iFound = iAllSame;
     129           0 :                     if(iFound==0) ++l2;
     130             :                 }
     131             :                 
     132             :                 // generate new entry
     133           0 :                 if(iFound==0)
     134             :                 {
     135           0 :                     memcpy(pfNewUniVertsOut+iUniqueNewVertices*iFloatsPerVert, pfVertexDataIn+index, sizeof(float)*iFloatsPerVert);
     136           0 :                     ++iUniqueNewVertices;
     137             :                 }
     138             : 
     139           0 :                 assert(piRemapTable[piVertexIDs[l]] == -1); // has not yet been assigned
     140           0 :                 piRemapTable[piVertexIDs[l]] = piCurNrUniqueVertices[0] + l2;
     141             :             }
     142             : 
     143           0 :             piCurNrUniqueVertices[0] += iUniqueNewVertices;
     144             :         }
     145             :         else
     146             :         {
     147           0 :             MergeVertsFast(piCurNrUniqueVertices, piRemapTable, pfVertexDataOut, piVertexIDs,
     148             :                            pfVertexDataIn, iNrVerticesIn, iFloatsPerVert,
     149             :                             iL_in, iR_in, iChannelNum+1);
     150           0 :         }
     151             :     }
     152             :     else
     153             :     {
     154           0 :         int iL=iL_in, iR=iR_in, index;
     155             : 
     156             :         // seperate (by fSep) all points between iL_in and iR_in in pTmpVert[]
     157           0 :         while(iL < iR)
     158             :         {
     159           0 :             int iReadyLeftSwap = 0;
     160           0 :             int iReadyRightSwap = 0;
     161           0 :             while(iReadyLeftSwap==0 && iL<iR)
     162             :             {
     163           0 :                 assert(iL>=iL_in && iL<=iR_in);
     164           0 :                 index = piVertexIDs[iL]*iFloatsPerVert+iChannelNum;
     165           0 :                 iReadyLeftSwap = !(pfVertexDataIn[index]<fAvg) ? 1 : 0;
     166           0 :                 if(iReadyLeftSwap==0) ++iL;
     167             :             }
     168           0 :             while(iReadyRightSwap==0 && iL<iR)
     169             :             {
     170           0 :                 assert(iR>=iL_in && iR<=iR_in);
     171           0 :                 index = piVertexIDs[iR]*iFloatsPerVert+iChannelNum;
     172           0 :                 iReadyRightSwap = pfVertexDataIn[index]<fAvg ? 1 : 0;
     173           0 :                 if(iReadyRightSwap==0) --iR;
     174             :             }
     175           0 :             assert( (iL<iR) || (iReadyLeftSwap==0 || iReadyRightSwap==0));
     176             : 
     177           0 :             if(iReadyLeftSwap!=0 && iReadyRightSwap!=0)
     178             :             {
     179           0 :                 int iID=0;
     180           0 :                 assert(iL<iR);
     181           0 :                 iID = piVertexIDs[iL];
     182           0 :                 piVertexIDs[iL] = piVertexIDs[iR];
     183           0 :                 piVertexIDs[iR] = iID;
     184           0 :                 ++iL; --iR;
     185             :             }
     186             :         }
     187             : 
     188           0 :         assert(iL==(iR+1) || (iL==iR));
     189           0 :         if(iL==iR)
     190             :         {
     191           0 :             const int index = piVertexIDs[iR]*iFloatsPerVert+iChannelNum;
     192           0 :             const int iReadyRightSwap = pfVertexDataIn[index]<fAvg ? 1 : 0;
     193           0 :             if(iReadyRightSwap!=0) ++iL;
     194           0 :             else --iR;
     195             :         }
     196             : 
     197             :         // recurse
     198           0 :         if(iL_in <= iR)
     199           0 :             MergeVertsFast(piCurNrUniqueVertices, piRemapTable, pfVertexDataOut, piVertexIDs,
     200             :                            pfVertexDataIn, iNrVerticesIn, iFloatsPerVert, iL_in, iR, iChannelNum);  // weld all left of fSep
     201           0 :         if(iL <= iR_in)
     202           0 :             MergeVertsFast(piCurNrUniqueVertices, piRemapTable, pfVertexDataOut, piVertexIDs,
     203             :                            pfVertexDataIn, iNrVerticesIn, iFloatsPerVert, iL, iR_in, iChannelNum);  // weld all right of (or equal to) fSep
     204             :     }
     205           3 : }
     206             : 

Generated by: LCOV version 1.13