7 #include "precompiled.h"
10 # pragma warning(disable:4189) // local variable is initialized but not referenced
14 # define GCC_VERSION (__GNUC__*100 + __GNUC_MINOR__)
16 # if GCC_VERSION >= 402 // older GCCs don't support the diagnostic pragma at all
17 # pragma GCC diagnostic ignored "-Wunused-variable"
57 #define M_PI 3.1415926535897932384626433832795
60 #define INTERNAL_RND_SORT_SEED 39871946
70 return (v1.
x == v2.
x) && (v1.
y == v2.
y) && (v1.
z == v2.
z);
109 return v.
x*v.
x + v.
y*v.
y + v.
z*v.
z;
124 return v1.
x*v2.
x + v1.
y*v2.
y + v1.
z*v2.
z;
131 return fabsf(fX) > FLT_MIN;
157 #define MARK_DEGENERATE 1
158 #define QUAD_ONE_DEGEN_TRI 2
159 #define GROUP_WITH_ANY 4
160 #define ORIENT_PRESERVING 8
166 int FaceNeighbors[3];
176 unsigned char vert_num[4];
192 static int Build4RuleGroups(
STriInfo pTriInfos[],
SGroup pGroups[],
int piGroupTrianglesBuffer[],
const int piTriListIn[],
const int iNrTrianglesIn);
194 const int iNrActiveGroups,
const int piTriListIn[],
const float fThresCos,
199 assert(iVert>=0 && iVert<4 && iFace>=0);
200 return (iFace<<2) | (iVert&0x3);
203 static void IndexToData(
int * piFace,
int * piVert,
const int iIndexIn)
205 piVert[0] = iIndexIn&0x3;
206 piFace[0] = iIndexIn>>2;
245 static void DegenPrologue(
STriInfo pTriInfos[],
int piTriList_out[],
const int iNrTrianglesIn,
const int iTotTris);
257 int * piTriListIn = NULL, * piGroupTrianglesBuffer = NULL;
261 int iNrTrianglesIn = 0, f=0, t=0, i=0;
262 int iNrTSPaces = 0, iTotTris = 0, iDegenTriangles = 0, iNrMaxGroups = 0;
263 int iNrActiveGroups = 0, index = 0;
266 const float fThresCos = (float) cos((fAngularThreshold*(
float)
M_PI)/180.0f);
277 for (f=0; f<iNrFaces; f++)
280 if (verts==3) ++iNrTrianglesIn;
281 else if(verts==4) iNrTrianglesIn += 2;
283 if (iNrTrianglesIn<=0)
return TFALSE;
286 piTriListIn = (
int *) malloc(
sizeof(
int)*3*iNrTrianglesIn);
288 if (piTriListIn==NULL || pTriInfos==NULL)
290 if (piTriListIn!=NULL) free(piTriListIn);
291 if (pTriInfos!=NULL) free(pTriInfos);
304 iTotTris = iNrTrianglesIn;
306 for (t=0; t<iTotTris; t++)
308 const int i0 = piTriListIn[t*3+0];
309 const int i1 = piTriListIn[t*3+1];
310 const int i2 = piTriListIn[t*3+2];
314 if (
veq(p0,p1) ||
veq(p0,p2) ||
veq(p1,p2))
320 iNrTrianglesIn = iTotTris - iDegenTriangles;
327 DegenPrologue(pTriInfos, piTriListIn, iNrTrianglesIn, iTotTris);
332 InitTriInfo(pTriInfos, piTriListIn, pContext, iNrTrianglesIn);
337 iNrMaxGroups = iNrTrianglesIn*3;
338 pGroups = (
SGroup *) malloc(
sizeof(
SGroup)*iNrMaxGroups);
339 piGroupTrianglesBuffer = (
int *) malloc(
sizeof(
int)*iNrTrianglesIn*3);
340 if (pGroups==NULL || piGroupTrianglesBuffer==NULL)
342 if (pGroups!=NULL) free(pGroups);
343 if (piGroupTrianglesBuffer!=NULL) free(piGroupTrianglesBuffer);
350 Build4RuleGroups(pTriInfos, pGroups, piGroupTrianglesBuffer, piTriListIn, iNrTrianglesIn);
361 free(piGroupTrianglesBuffer);
364 memset(psTspace, 0,
sizeof(
STSpace)*iNrTSPaces);
365 for (t=0; t<iNrTSPaces; t++)
367 psTspace[t].
vOs.
x=1.0f; psTspace[t].
vOs.
y=0.0f; psTspace[t].
vOs.
z=0.0f; psTspace[t].
fMagS = 1.0f;
368 psTspace[t].
vOt.
x=0.0f; psTspace[t].
vOt.
y=1.0f; psTspace[t].
vOt.
z=0.0f; psTspace[t].
fMagT = 1.0f;
375 bRes =
GenerateTSpaces(psTspace, pTriInfos, pGroups, iNrActiveGroups, piTriListIn, fThresCos, pContext);
380 free(piGroupTrianglesBuffer);
385 free(pTriInfos); free(piTriListIn); free(psTspace);
394 DegenEpilogue(psTspace, pTriInfos, piTriListIn, pContext, iNrTrianglesIn, iTotTris);
396 free(pTriInfos); free(piTriListIn);
399 for (f=0; f<iNrFaces; f++)
402 if (verts!=3 && verts!=4)
continue;
427 for (i=0; i<verts; i++)
429 const STSpace * pTSpace = &psTspace[index];
430 float tang[] = {pTSpace->
vOs.
x, pTSpace->
vOs.
y, pTSpace->
vOs.
z};
431 float bitang[] = {pTSpace->
vOt.
x, pTSpace->
vOt.
y, pTSpace->
vOt.
z};
458 #define NOINLINE __declspec(noinline)
460 #define NOINLINE __attribute__ ((noinline))
468 const float fIndex =
g_iCells * ((fVal-fMin)/(fMax-fMin));
469 const int iIndex = fIndex<0?0:((int)fIndex);
481 int * piHashTable=NULL, * piHashCount=NULL, * piHashOffsets=NULL, * piHashCount2=NULL;
483 int i=0, iChannel=0, k=0, e=0;
487 for (i=1; i<(iNrTrianglesIn*3); i++)
489 const int index = piTriList_in_and_out[i];
492 if (vMin.
x > vP.
x) vMin.
x = vP.
x;
493 else if(vMax.x < vP.
x) vMax.x = vP.
x;
494 if (vMin.
y > vP.
y) vMin.
y = vP.
y;
495 else if(vMax.y < vP.
y) vMax.y = vP.
y;
496 if (vMin.
z > vP.
z) vMin.
z = vP.
z;
497 else if(vMax.z < vP.
z) vMax.z = vP.
z;
500 vDim =
vsub(vMax,vMin);
502 fMin = vMin.
x; fMax=vMax.x;
503 if (vDim.y>vDim.x && vDim.y>vDim.z)
506 fMin = vMin.
y, fMax=vMax.y;
508 else if(vDim.z>vDim.x)
511 fMin = vMin.
z, fMax=vMax.z;
515 piHashTable = (
int *) malloc(
sizeof(
int)*iNrTrianglesIn*3);
516 piHashCount = (
int *) malloc(
sizeof(
int)*
g_iCells);
517 piHashOffsets = (
int *) malloc(
sizeof(
int)*
g_iCells);
518 piHashCount2 = (
int *) malloc(
sizeof(
int)*
g_iCells);
520 if (piHashTable==NULL || piHashCount==NULL || piHashOffsets==NULL || piHashCount2==NULL)
522 if (piHashTable!=NULL) free(piHashTable);
523 if (piHashCount!=NULL) free(piHashCount);
524 if (piHashOffsets!=NULL) free(piHashOffsets);
525 if (piHashCount2!=NULL) free(piHashCount2);
529 memset(piHashCount, 0,
sizeof(
int)*
g_iCells);
530 memset(piHashCount2, 0,
sizeof(
int)*g_iCells);
533 for (i=0; i<(iNrTrianglesIn*3); i++)
535 const int index = piTriList_in_and_out[i];
537 const float fVal = iChannel==0 ? vP.
x : (iChannel==1 ? vP.
y : vP.
z);
539 ++piHashCount[iCell];
545 piHashOffsets[k]=piHashOffsets[k-1]+piHashCount[k-1];
548 for (i=0; i<(iNrTrianglesIn*3); i++)
550 const int index = piTriList_in_and_out[i];
552 const float fVal = iChannel==0 ? vP.
x : (iChannel==1 ? vP.
y : vP.
z);
556 assert(piHashCount2[iCell]<piHashCount[iCell]);
557 pTable = &piHashTable[piHashOffsets[iCell]];
558 pTable[piHashCount2[iCell]] = i;
559 ++piHashCount2[iCell];
562 assert(piHashCount2[k] == piHashCount[k]);
566 iMaxCount = piHashCount[0];
568 if (iMaxCount<piHashCount[k])
569 iMaxCount=piHashCount[k];
577 int * pTable = &piHashTable[piHashOffsets[k]];
578 const int iEntries = piHashCount[k];
579 if (iEntries < 2)
continue;
583 for (e=0; e<iEntries; e++)
587 pTmpVert[e].
vert[0] = vP.
x; pTmpVert[e].
vert[1] = vP.
y;
588 pTmpVert[e].
vert[2] = vP.
z; pTmpVert[e].
index = i;
590 MergeVertsFast(piTriList_in_and_out, pTmpVert, pContext, 0, iEntries-1);
596 if (pTmpVert!=NULL) { free(pTmpVert); }
605 int c=0, l=0, channel=0;
606 float fvMin[3], fvMax[3];
607 float dx=0, dy=0, dz=0, fSep=0;
609 { fvMin[c]=pTmpVert[iL_in].
vert[c]; fvMax[c]=fvMin[c]; }
610 for (l=(iL_in+1); l<=iR_in; l++)
612 if (fvMin[c]>pTmpVert[l].vert[c]) fvMin[c]=pTmpVert[l].
vert[c];
613 else if(fvMax[c]<pTmpVert[l].vert[c]) fvMax[c]=pTmpVert[l].
vert[c];
615 dx = fvMax[0]-fvMin[0];
616 dy = fvMax[1]-fvMin[1];
617 dz = fvMax[2]-fvMin[2];
620 if (dy>dx && dy>dz) channel=1;
621 else if(dz>dx) channel=2;
623 fSep = 0.5f*(fvMax[channel]+fvMin[channel]);
627 if (fSep>=fvMax[channel] || fSep<=fvMin[channel])
630 for (l=iL_in; l<=iR_in; l++)
632 int i = pTmpVert[l].
index;
633 const int index = piTriList_in_and_out[i];
639 int l2=iL_in, i2rec=-1;
640 while (l2<l && bNotFound)
642 const int i2 = pTmpVert[l2].
index;
643 const int index2 = piTriList_in_and_out[i2];
650 if (vP.
x==vP2.
x && vP.
y==vP2.
y && vP.
z==vP2.
z &&
651 vN.
x==vN2.
x && vN.
y==vN2.
y && vN.
z==vN2.
z &&
652 vT.
x==vT2.
x && vT.
y==vT2.
y && vT.
z==vT2.
z)
660 piTriList_in_and_out[i] = piTriList_in_and_out[i2rec];
665 int iL=iL_in, iR=iR_in;
666 assert((iR_in-iL_in)>0);
672 while ((!bReadyLeftSwap) && iL<iR)
674 assert(iL>=iL_in && iL<=iR_in);
675 bReadyLeftSwap = !(pTmpVert[iL].
vert[channel]<fSep);
676 if (!bReadyLeftSwap) ++iL;
678 while ((!bReadyRightSwap) && iL<iR)
680 assert(iR>=iL_in && iR<=iR_in);
681 bReadyRightSwap = pTmpVert[iR].
vert[channel]<fSep;
682 if (!bReadyRightSwap) --iR;
684 assert( (iL<iR) || !(bReadyLeftSwap && bReadyRightSwap) );
686 if (bReadyLeftSwap && bReadyRightSwap)
690 pTmpVert[iL] = pTmpVert[iR];
696 assert(iL==(iR+1) || (iL==iR));
699 const tbool bReadyRightSwap = pTmpVert[iR].
vert[channel]<fSep;
700 if (bReadyRightSwap) ++iL;
706 MergeVertsFast(piTriList_in_and_out, pTmpVert, pContext, iL_in, iR);
708 MergeVertsFast(piTriList_in_and_out, pTmpVert, pContext, iL, iR_in);
716 for (e=0; e<iEntries; e++)
719 const int index = piTriList_in_and_out[i];
726 while (e2<e && bNotFound)
728 const int i2 = pTable[e2];
729 const int index2 = piTriList_in_and_out[i2];
735 if (
veq(vP,vP2) &&
veq(vN,vN2) &&
veq(vT,vT2))
743 piTriList_in_and_out[i] = piTriList_in_and_out[i2rec];
749 int iNumUniqueVerts = 0, t=0, i=0;
750 for (t=0; t<iNrTrianglesIn; t++)
754 const int offs = t*3 + i;
755 const int index = piTriList_in_and_out[offs];
762 int t2=0, index2rec=-1;
763 while (!bFound && t2<=t)
766 while (!bFound && j<3)
768 const int index2 = piTriList_in_and_out[t2*3 + j];
773 if (
veq(vP,vP2) &&
veq(vN,vN2) &&
veq(vT,vT2))
783 if (index2rec == index) { ++iNumUniqueVerts; }
785 piTriList_in_and_out[offs] = index2rec;
792 int iTSpacesOffs = 0, f=0, t=0;
793 int iDstTriIndex = 0;
797 if (verts!=3 && verts!=4)
continue;
804 unsigned char * pVerts = pTriInfos[iDstTriIndex].
vert_num;
805 pVerts[0]=0; pVerts[1]=1; pVerts[2]=2;
806 piTriList_out[iDstTriIndex*3+0] =
MakeIndex(f, 0);
807 piTriList_out[iDstTriIndex*3+1] =
MakeIndex(f, 1);
808 piTriList_out[iDstTriIndex*3+2] =
MakeIndex(f, 2);
832 tbool bQuadDiagIs_02;
833 if (distSQ_02<distSQ_13)
834 bQuadDiagIs_02 =
TTRUE;
835 else if(distSQ_13<distSQ_02)
846 bQuadDiagIs_02 = distSQ_13<distSQ_02 ?
TFALSE :
TTRUE;
852 unsigned char * pVerts_A = pTriInfos[iDstTriIndex].
vert_num;
853 pVerts_A[0]=0; pVerts_A[1]=1; pVerts_A[2]=2;
855 piTriList_out[iDstTriIndex*3+0] = i0;
856 piTriList_out[iDstTriIndex*3+1] = i1;
857 piTriList_out[iDstTriIndex*3+2] = i2;
860 unsigned char * pVerts_B = pTriInfos[iDstTriIndex].
vert_num;
861 pVerts_B[0]=0; pVerts_B[1]=2; pVerts_B[2]=3;
863 piTriList_out[iDstTriIndex*3+0] = i0;
864 piTriList_out[iDstTriIndex*3+1] = i2;
865 piTriList_out[iDstTriIndex*3+2] = i3;
871 unsigned char * pVerts_A = pTriInfos[iDstTriIndex].
vert_num;
872 pVerts_A[0]=0; pVerts_A[1]=1; pVerts_A[2]=3;
874 piTriList_out[iDstTriIndex*3+0] = i0;
875 piTriList_out[iDstTriIndex*3+1] = i1;
876 piTriList_out[iDstTriIndex*3+2] = i3;
879 unsigned char * pVerts_B = pTriInfos[iDstTriIndex].
vert_num;
880 pVerts_B[0]=1; pVerts_B[1]=2; pVerts_B[2]=3;
882 piTriList_out[iDstTriIndex*3+0] = i1;
883 piTriList_out[iDstTriIndex*3+1] = i2;
884 piTriList_out[iDstTriIndex*3+2] = i3;
890 iTSpacesOffs += verts;
891 assert(iDstTriIndex<=iNrTrianglesIn);
894 for (t=0; t<iNrTrianglesIn; t++)
895 pTriInfos[t].iFlag = 0;
904 SVec3 res;
float pos[3];
907 res.
x=pos[0]; res.
y=pos[1]; res.
z=pos[2];
914 SVec3 res;
float norm[3];
917 res.
x=norm[0]; res.
y=norm[1]; res.
z=norm[2];
924 SVec3 res;
float texc[2];
927 res.
x=texc[0]; res.
y=texc[1]; res.
z=1.0f;
953 const float t21x = t2.
x-t1.
x;
954 const float t21y = t2.
y-t1.
y;
955 const float t31x = t3.
x-t1.
x;
956 const float t31y = t3.
y-t1.
y;
958 const float fSignedAreaSTx2 = t21x*t31y - t21y*t31x;
960 return fSignedAreaSTx2<0 ? (-fSignedAreaSTx2) : fSignedAreaSTx2;
969 for (f=0; f<iNrTrianglesIn; f++)
975 pTriInfos[f].
vOs.
x=0.0f; pTriInfos[f].
vOs.
y=0.0f; pTriInfos[f].
vOs.
z=0.0f;
976 pTriInfos[f].
vOt.
x=0.0f; pTriInfos[f].
vOt.
y=0.0f; pTriInfos[f].
vOt.
z=0.0f;
977 pTriInfos[f].
fMagS = 0;
978 pTriInfos[f].
fMagT = 0;
985 for (f=0; f<iNrTrianglesIn; f++)
995 const float t21x = t2.
x-t1.
x;
996 const float t21y = t2.
y-t1.
y;
997 const float t31x = t3.
x-t1.
x;
998 const float t31y = t3.
y-t1.
y;
1002 const float fSignedAreaSTx2 = t21x*t31y - t21y*t31x;
1009 if (
NotZero(fSignedAreaSTx2) )
1011 const float fAbsArea = fabsf(fSignedAreaSTx2);
1012 const float fLenOs =
Length(vOs);
1013 const float fLenOt =
Length(vOt);
1015 if (
NotZero(fLenOs) ) pTriInfos[f].vOs =
vscale(fS/fLenOs, vOs);
1016 if (
NotZero(fLenOt) ) pTriInfos[f].vOt =
vscale(fS/fLenOt, vOt);
1019 pTriInfos[f].
fMagS = fLenOs / fAbsArea;
1020 pTriInfos[f].
fMagT = fLenOt / fAbsArea;
1029 while (t<(iNrTrianglesIn-1))
1040 if ((bIsDeg_a||bIsDeg_b)==
TFALSE)
1045 if (bOrientA!=bOrientB)
1051 bChooseOrientFirstTri =
TTRUE;
1055 const int t0 = bChooseOrientFirstTri ? t : (t+1);
1056 const int t1 = bChooseOrientFirstTri ? (t+1) : t;
1090 const int iNrMaxGroups = iNrTrianglesIn*3;
1091 int iNrActiveGroups = 0;
1092 int iOffset = 0, f=0, i=0;
1093 for (f=0; f<iNrTrianglesIn; f++)
1098 if ((pTriInfos[f].iFlag&
GROUP_WITH_ANY)==0 && pTriInfos[f].AssignedGroup[i]==NULL)
1101 int neigh_indexL, neigh_indexR;
1102 const int vert_index = piTriListIn[f*3+i];
1103 assert(iNrActiveGroups<iNrMaxGroups);
1115 if (neigh_indexL>=0)
1117 const tbool bAnswer =
1119 pTriInfos[f].AssignedGroup[i] );
1123 assert(bAnswer || bDiff);
1125 if (neigh_indexR>=0)
1127 const tbool bAnswer =
1129 pTriInfos[f].AssignedGroup[i] );
1133 assert(bAnswer || bDiff);
1141 assert(iOffset <= iNrMaxGroups);
1146 return iNrActiveGroups;
1156 const int iMyTriIndex,
SGroup * pGroup)
1158 STriInfo * pMyTriInfo = &psTriInfos[iMyTriIndex];
1162 const int * pVerts = &piTriListIn[3*iMyTriIndex+0];
1164 if (pVerts[0]==iVertRep) i=0;
1165 else if(pVerts[1]==iVertRep) i=1;
1166 else if(pVerts[2]==iVertRep) i=2;
1167 assert(i>=0 && i<3);
1195 const int neigh_indexR = pMyTriInfo->
FaceNeighbors[i>0?(i-1):2];
1196 if (neigh_indexL>=0)
1197 AssignRecur(piTriListIn, psTriInfos, neigh_indexL, pGroup);
1198 if (neigh_indexR>=0)
1199 AssignRecur(piTriListIn, psTriInfos, neigh_indexR, pGroup);
1211 static void QuickSort(
int* pSortBuffer,
int iLeft,
int iRight,
unsigned int uSeed);
1215 const int iNrActiveGroups,
const int piTriListIn[],
const float fThresCos,
1218 STSpace * pSubGroupTspace = NULL;
1220 int * pTmpMembers = NULL;
1221 int iMaxNrFaces=0, iUniqueTspaces=0, g=0, i=0;
1222 for (g=0; g<iNrActiveGroups; g++)
1223 if (iMaxNrFaces < pGroups[g].iNrFaces)
1226 if (iMaxNrFaces == 0)
return TTRUE;
1229 pSubGroupTspace = (
STSpace *) malloc(
sizeof(
STSpace)*iMaxNrFaces);
1231 pTmpMembers = (
int *) malloc(
sizeof(
int)*iMaxNrFaces);
1232 if (pSubGroupTspace==NULL || pUniSubGroups==NULL || pTmpMembers==NULL)
1234 if (pSubGroupTspace!=NULL) free(pSubGroupTspace);
1235 if (pUniSubGroups!=NULL) free(pUniSubGroups);
1236 if (pTmpMembers!=NULL) free(pTmpMembers);
1242 for (g=0; g<iNrActiveGroups; g++)
1244 const SGroup * pGroup = &pGroups[g];
1245 int iUniqueSubGroups = 0, s=0;
1250 int index=-1, iVertIndex=-1, iOF_1=-1, iMembers=0, j=0, l=0;
1254 if (pTriInfos[f].AssignedGroup[0]==pGroup) index=0;
1255 else if(pTriInfos[f].AssignedGroup[1]==pGroup) index=1;
1256 else if(pTriInfos[f].AssignedGroup[2]==pGroup) index=2;
1257 assert(index>=0 && index<3);
1259 iVertIndex = piTriListIn[f*3+index];
1266 vOs =
vsub(pTriInfos[f].vOs,
vscale(
vdot(n,pTriInfos[f].vOs), n));
1267 vOt =
vsub(pTriInfos[f].vOt,
vscale(
vdot(n,pTriInfos[f].vOt), n));
1291 const float fCosS =
vdot(vOs,vOs2);
1292 const float fCosT =
vdot(vOt,vOt2);
1294 assert(f!=t || bSameOrgFace);
1295 if (bAny || bSameOrgFace || (fCosS>fThresCos && fCosT>fThresCos))
1296 pTmpMembers[iMembers++] = t;
1306 QuickSort(pTmpMembers, 0, iMembers-1, uSeed);
1312 while (l<iUniqueSubGroups && !bFound)
1319 assert(bFound || l==iUniqueSubGroups);
1326 int * pIndices = (
int *) malloc(
sizeof(
int)*iMembers);
1331 for (s=0; s<iUniqueSubGroups; s++)
1332 free(pUniSubGroups[s].pTriMembers);
1333 free(pUniSubGroups);
1335 free(pSubGroupTspace);
1338 pUniSubGroups[iUniqueSubGroups].
iNrFaces = iMembers;
1339 pUniSubGroups[iUniqueSubGroups].
pTriMembers = pIndices;
1340 memcpy(pIndices, tmp_group.
pTriMembers, iMembers*
sizeof(
int));
1341 pSubGroupTspace[iUniqueSubGroups] =
1349 const int iVert = pTriInfos[f].
vert_num[index];
1350 STSpace * pTS_out = &psTspace[iOffs+iVert];
1355 *pTS_out =
AvgTSpace(pTS_out, &pSubGroupTspace[l]);
1362 *pTS_out = pSubGroupTspace[l];
1370 for (s=0; s<iUniqueSubGroups; s++)
1371 free(pUniSubGroups[s].pTriMembers);
1372 iUniqueTspaces += iUniqueSubGroups;
1376 free(pUniSubGroups);
1378 free(pSubGroupTspace);
1387 float fAngleSum = 0;
1393 for (face=0; face<iFaces; face++)
1395 const int f = face_indices[face];
1400 SVec3 n, vOs, vOt, p0, p1, p2, v1, v2;
1401 float fCos, fAngle, fMagS, fMagT;
1402 int i=-1, index=-1, i0=-1, i1=-1, i2=-1;
1403 if (piTriListIn[3*f+0]==iVertexRepresentitive) i=0;
1404 else if(piTriListIn[3*f+1]==iVertexRepresentitive) i=1;
1405 else if(piTriListIn[3*f+2]==iVertexRepresentitive) i=2;
1406 assert(i>=0 && i<3);
1409 index = piTriListIn[3*f+i];
1411 vOs =
vsub(pTriInfos[f].vOs,
vscale(
vdot(n,pTriInfos[f].vOs), n));
1412 vOt =
vsub(pTriInfos[f].vOt,
vscale(
vdot(n,pTriInfos[f].vOt), n));
1416 i2 = piTriListIn[3*f + (i<2?(i+1):0)];
1417 i1 = piTriListIn[3*f + i];
1418 i0 = piTriListIn[3*f + (i>0?(i-1):2)];
1432 fCos =
vdot(v1,v2); fCos=fCos>1?1:(fCos<(-1) ? (-1) : fCos);
1433 fAngle = (float) acos(fCos);
1434 fMagS = pTriInfos[f].
fMagS;
1435 fMagT = pTriInfos[f].
fMagT;
1439 res.
fMagS+=(fAngle*fMagS);
1440 res.
fMagT+=(fAngle*fMagT);
1441 fAngleSum += fAngle;
1450 res.
fMagS /= fAngleSum;
1451 res.
fMagT /= fAngleSum;
1462 while (i<pg1->iNrFaces && bStillSame)
1465 if (bStillSame) ++i;
1470 static void QuickSort(
int* pSortBuffer,
int iLeft,
int iRight,
unsigned int uSeed)
1472 int iL, iR, n, index, iMid, iTmp;
1475 unsigned int t=uSeed&31;
1476 t=(uSeed<<t)|(uSeed>>(32-t));
1480 iL=iLeft; iR=iRight;
1483 index = (int) (uSeed%n);
1485 iMid=pSortBuffer[index + iL];
1490 while (pSortBuffer[iL] < iMid)
1492 while (pSortBuffer[iR] > iMid)
1497 iTmp = pSortBuffer[iL];
1498 pSortBuffer[iL] = pSortBuffer[iR];
1499 pSortBuffer[iR] = iTmp;
1506 QuickSort(pSortBuffer, iLeft, iR, uSeed);
1508 QuickSort(pSortBuffer, iL, iRight, uSeed);
1514 static void QuickSortEdges(
SEdge * pSortBuffer,
int iLeft,
int iRight,
const int channel,
unsigned int uSeed);
1515 static void GetEdge(
int * i0_out,
int * i1_out,
int * edgenum_out,
const int indices[],
const int i0_in,
const int i1_in);
1521 int iEntries=0, iCurStartIndex=-1, f=0, i=0;
1522 for (f=0; f<iNrTrianglesIn; f++)
1525 const int i0 = piTriListIn[f*3+i];
1526 const int i1 = piTriListIn[f*3+(i<2?(i+1):0)];
1527 pEdges[f*3+i].
i0 = i0 < i1 ? i0 : i1;
1528 pEdges[f*3+i].
i1 = !(i0 < i1) ? i0 : i1;
1529 pEdges[f*3+i].
f = f;
1538 iEntries = iNrTrianglesIn*3;
1540 for (i=1; i<iEntries; i++)
1542 if (pEdges[iCurStartIndex].i0 != pEdges[i].i0)
1544 const int iL = iCurStartIndex;
1556 for (i=1; i<iEntries; i++)
1558 if (pEdges[iCurStartIndex].i0 != pEdges[i].i0 || pEdges[iCurStartIndex].i1 != pEdges[i].i1)
1560 const int iL = iCurStartIndex;
1569 for (i=0; i<iEntries; i++)
1571 const int i0=pEdges[i].
i0;
1572 const int i1=pEdges[i].
i1;
1573 const int f = pEdges[i].
f;
1574 tbool bUnassigned_A;
1577 int edgenum_A, edgenum_B=0;
1578 GetEdge(&i0_A, &i1_A, &edgenum_A, &piTriListIn[f*3], i0, i1);
1586 while (j<iEntries && i0==pEdges[j].i0 && i1==pEdges[j].i1 && bNotFound)
1588 tbool bUnassigned_B;
1592 GetEdge(&i1_B, &i0_B, &edgenum_B, &piTriListIn[t*3], pEdges[j].i0, pEdges[j].i1);
1595 if (i0_A==i0_B && i1_A==i1_B && bUnassigned_B)
1603 int t = pEdges[j].
f;
1615 for (f=0; f<iNrTrianglesIn; f++)
1620 if (pTriInfos[f].FaceNeighbors[i] == -1)
1622 const int i0_A = piTriListIn[f*3+i];
1623 const int i1_A = piTriListIn[f*3+(i<2?(i+1):0)];
1628 while (!bFound && t<iNrTrianglesIn)
1633 while (!bFound && j<3)
1636 const int i1_B = piTriListIn[t*3+j];
1637 const int i0_B = piTriListIn[t*3+(j<2?(j+1):0)];
1639 if (i0_A==i0_B && i1_A==i1_B)
1664 int iL, iR, n, index, iMid;
1668 const int iElems = iRight-iLeft+1;
1669 if (iElems<2)
return;
1672 if (pSortBuffer[iLeft].array[channel] > pSortBuffer[iRight].array[channel])
1674 sTmp = pSortBuffer[iLeft];
1675 pSortBuffer[iLeft] = pSortBuffer[iRight];
1676 pSortBuffer[iRight] = sTmp;
1683 t=(uSeed<<t)|(uSeed>>(32-t));
1687 iL=iLeft, iR=iRight;
1690 index = (int) (uSeed%n);
1692 iMid=pSortBuffer[index + iL].
array[channel];
1696 while (pSortBuffer[iL].array[channel] < iMid)
1698 while (pSortBuffer[iR].array[channel] > iMid)
1703 sTmp = pSortBuffer[iL];
1704 pSortBuffer[iL] = pSortBuffer[iR];
1705 pSortBuffer[iR] = sTmp;
1718 static void GetEdge(
int * i0_out,
int * i1_out,
int * edgenum_out,
const int indices[],
const int i0_in,
const int i1_in)
1723 if (indices[0]==i0_in || indices[0]==i1_in)
1726 if (indices[1]==i0_in || indices[1]==i1_in)
1729 i0_out[0]=indices[0];
1730 i1_out[0]=indices[1];
1735 i0_out[0]=indices[2];
1736 i1_out[0]=indices[0];
1743 i0_out[0]=indices[1];
1744 i1_out[0]=indices[2];
1754 int iNextGoodTriangleSearchIndex=-1;
1755 tbool bStillFindingGoodOnes;
1759 while (t<(iTotTris-1))
1767 if ((bIsDeg_a^bIsDeg_b)!=0)
1780 iNextGoodTriangleSearchIndex = 1;
1782 bStillFindingGoodOnes =
TTRUE;
1783 while (t<iNrTrianglesIn && bStillFindingGoodOnes)
1788 if (iNextGoodTriangleSearchIndex < (t+2))
1789 iNextGoodTriangleSearchIndex = t+2;
1796 while (bJustADegenerate && iNextGoodTriangleSearchIndex<iTotTris)
1799 if (bIsGood) bJustADegenerate=
TFALSE;
1800 else ++iNextGoodTriangleSearchIndex;
1804 t1 = iNextGoodTriangleSearchIndex;
1805 ++iNextGoodTriangleSearchIndex;
1806 assert(iNextGoodTriangleSearchIndex > (t+1));
1809 if (!bJustADegenerate)
1814 const int index = piTriList_out[t0*3+i];
1815 piTriList_out[t0*3+i] = piTriList_out[t1*3+i];
1816 piTriList_out[t1*3+i] = index;
1819 const STriInfo tri_info = pTriInfos[t0];
1820 pTriInfos[t0] = pTriInfos[t1];
1821 pTriInfos[t1] = tri_info;
1825 bStillFindingGoodOnes =
TFALSE;
1828 if (bStillFindingGoodOnes) ++t;
1831 assert(bStillFindingGoodOnes);
1832 assert(iNrTrianglesIn == t);
1840 for (t=iNrTrianglesIn; t<iTotTris; t++)
1850 const int index1 = piTriListIn[t*3+i];
1854 while (bNotFound && j<(3*iNrTrianglesIn))
1856 const int index2 = piTriListIn[j];
1857 if (index1==index2) bNotFound=
TFALSE;
1863 const int iTri = j/3;
1864 const int iVert = j%3;
1865 const int iSrcVert=pTriInfos[iTri].
vert_num[iVert];
1867 const int iDstVert=pTriInfos[t].
vert_num[i];
1871 psTspace[iDstOffs+iDstVert] = psTspace[iSrcOffs+iSrcVert];
1878 for (t=0; t<iNrTrianglesIn; t++)
1887 unsigned char * pV = pTriInfos[t].
vert_num;
1888 int iFlag = (1<<pV[0]) | (1<<pV[1]) | (1<<pV[2]);
1889 int iMissingIndex = 0;
1890 if ((iFlag&2)==0) iMissingIndex=1;
1891 else if((iFlag&4)==0) iMissingIndex=2;
1892 else if((iFlag&8)==0) iMissingIndex=3;
1898 while (bNotFound && i<3)
1900 const int iVert = pV[i];
1905 psTspace[iOffs+iMissingIndex] = psTspace[iOffs+iVert];
SMikkTSpaceInterface * m_pInterface
#define TFALSE
Copyright (C) 2011 by Morten S.
static void InitTriInfo(STriInfo pTriInfos[], const int piTriListIn[], const SMikkTSpaceContext *pContext, const int iNrTrianglesIn)
static SVec3 vscale(const float fS, const SVec3 v)
static tbool AssignRecur(const int piTriListIn[], STriInfo psTriInfos[], const int iMyTriIndex, SGroup *pGroup)
float vdot(float *va, float *vb)
Return dot product of length 3 vectors va and vb.
static SVec3 GetTexCoord(const SMikkTSpaceContext *pContext, const int index)
int(* m_getNumVerticesOfFace)(const SMikkTSpaceContext *pContext, const int iFace)
static void MergeVertsFast(int piTriList_in_and_out[], STmpVert pTmpVert[], const SMikkTSpaceContext *pContext, const int iL_in, const int iR_in)
static float CalcTexArea(const SMikkTSpaceContext *pContext, const int indices[])
void(* m_setTSpace)(const SMikkTSpaceContext *pContext, const float fvTangent[], const float fvBiTangent[], const float fMagS, const float fMagT, const tbool bIsOrientationPreserving, const int iFace, const int iVert)
void(* m_getNormal)(const SMikkTSpaceContext *pContext, float fvNormOut[], const int iFace, const int iVert)
static void BuildNeighborsFast(STriInfo pTriInfos[], SEdge *pEdges, const int piTriListIn[], const int iNrTrianglesIn)
static SVec3 vsub(const SVec3 v1, const SVec3 v2)
static void GenerateSharedVerticesIndexList(int piTriList_in_and_out[], const SMikkTSpaceContext *pContext, const int iNrTrianglesIn)
static int GenerateInitialVerticesIndexList(STriInfo pTriInfos[], int piTriList_out[], const SMikkTSpaceContext *pContext, const int iNrTrianglesIn)
static void GetEdge(int *i0_out, int *i1_out, int *edgenum_out, const int indices[], const int i0_in, const int i1_in)
#define INTERNAL_RND_SORT_SEED
static SVec3 GetNormal(const SMikkTSpaceContext *pContext, const int index)
static int MakeIndex(const int iFace, const int iVert)
tbool bOrientPreservering
static SVec3 vadd(const SVec3 v1, const SVec3 v2)
static void IndexToData(int *piFace, int *piVert, const int iIndexIn)
static tbool GenerateTSpaces(STSpace psTspace[], const STriInfo pTriInfos[], const SGroup pGroups[], const int iNrActiveGroups, const int piTriListIn[], const float fThresCos, const SMikkTSpaceContext *pContext)
static void QuickSortEdges(SEdge *pSortBuffer, int iLeft, int iRight, const int channel, unsigned int uSeed)
static tbool CompareSubGroups(const SSubGroup *pg1, const SSubGroup *pg2)
static void QuickSort(int *pSortBuffer, int iLeft, int iRight, unsigned int uSeed)
static void MergeVertsSlow(int piTriList_in_and_out[], const SMikkTSpaceContext *pContext, const int pTable[], const int iEntries)
static STSpace AvgTSpace(const STSpace *pTS0, const STSpace *pTS1)
int(* m_getNumFaces)(const SMikkTSpaceContext *pContext)
tbool genTangSpaceDefault(const SMikkTSpaceContext *pContext)
SGroup * AssignedGroup[3]
static void DegenPrologue(STriInfo pTriInfos[], int piTriList_out[], const int iNrTrianglesIn, const int iTotTris)
static tbool VNotZero(const SVec3 v)
void(* m_setTSpaceBasic)(const SMikkTSpaceContext *pContext, const float fvTangent[], const float fSign, const int iFace, const int iVert)
static int Build4RuleGroups(STriInfo pTriInfos[], SGroup pGroups[], int piGroupTrianglesBuffer[], const int piTriListIn[], const int iNrTrianglesIn)
void(* m_getPosition)(const SMikkTSpaceContext *pContext, float fvPosOut[], const int iFace, const int iVert)
static void GenerateSharedVerticesIndexListSlow(int piTriList_in_and_out[], const SMikkTSpaceContext *pContext, const int iNrTrianglesIn)
tbool genTangSpace(const SMikkTSpaceContext *pContext, const float fAngularThreshold)
static SVec3 GetPosition(const SMikkTSpaceContext *pContext, const int index)
static tbool NotZero(const float fX)
void(* m_getTexCoord)(const SMikkTSpaceContext *pContext, float fvTexcOut[], const int iFace, const int iVert)
static float LengthSquared(const SVec3 v)
unsigned char vert_num[4]
int iVertexRepresentitive
static tbool veq(const SVec3 v1, const SVec3 v2)
NOINLINE int FindGridCell(const float fMin, const float fMax, const float fVal)
static SVec3 Normalize(const SVec3 v)
int tbool
Copyright (C) 2011 by Morten S.
static float Length(const SVec3 v)
static STSpace EvalTspace(int face_indices[], const int iFaces, const int piTriListIn[], const STriInfo pTriInfos[], const SMikkTSpaceContext *pContext, const int iVertexRepresentitive)
static void DegenEpilogue(STSpace psTspace[], STriInfo pTriInfos[], int piTriListIn[], const SMikkTSpaceContext *pContext, const int iNrTrianglesIn, const int iTotTris)
static void AddTriToGroup(SGroup *pGroup, const int iTriIndex)
#define QUAD_ONE_DEGEN_TRI
static void BuildNeighborsSlow(STriInfo pTriInfos[], const int piTriListIn[], const int iNrTrianglesIn)
#define ORIENT_PRESERVING