diff options
| author | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
|---|---|---|
| committer | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
| commit | 3bf9df6b2785fa6d951086978a3e66f49427166a (patch) | |
| tree | 2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /utils/studiomdl/tristrip.cpp | |
| download | archived-source-engine-2018-hl2-src-master.tar.xz archived-source-engine-2018-hl2-src-master.zip | |
Diffstat (limited to 'utils/studiomdl/tristrip.cpp')
| -rw-r--r-- | utils/studiomdl/tristrip.cpp | 350 |
1 files changed, 350 insertions, 0 deletions
diff --git a/utils/studiomdl/tristrip.cpp b/utils/studiomdl/tristrip.cpp new file mode 100644 index 0000000..2a42836 --- /dev/null +++ b/utils/studiomdl/tristrip.cpp @@ -0,0 +1,350 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// + +// tristrip - convert triangle list into tristrips and fans + +#pragma warning( disable : 4244 ) +#pragma warning( disable : 4237 ) +#pragma warning( disable : 4305 ) + + +#include <stdio.h> +#include <stdlib.h> +#include <sys/stat.h> + +#include "cmdlib.h" +#include "lbmlib.h" +#include "scriplib.h" +#include "mathlib/mathlib.h" +#include "..\..\engine\studio.h" +#include "studiomdl.h" + +int used[MAXSTUDIOTRIANGLES]; + +// the command list holds counts and s/t values that are valid for +// every frame +short commands[MAXSTUDIOTRIANGLES * 13]; +int numcommands; + +// all frames will have their vertexes rearranged and expanded +// so they are in the order expected by the command list + +int allverts, alltris; + +int stripverts[MAXSTUDIOTRIANGLES+2]; +int striptris[MAXSTUDIOTRIANGLES+2]; +int stripcount; + +int neighbortri[MAXSTUDIOTRIANGLES][3]; +int neighboredge[MAXSTUDIOTRIANGLES][3]; + + +s_trianglevert_t (*triangles)[3]; +s_mesh_t *pmesh; + + +void FindNeighbor (int starttri, int startv) +{ + s_trianglevert_t m1, m2; + int j; + s_trianglevert_t *last, *check; + int k; + + // used[starttri] |= (1 << startv); + + last = &triangles[starttri][0]; + + m1 = last[(startv+1)%3]; + m2 = last[(startv+0)%3]; + + for (j=starttri+1, check=&triangles[starttri+1][0] ; j<pmesh->numtris ; j++, check += 3) + { + if (used[j] == 7) + continue; + for (k=0 ; k<3 ; k++) + { + if (memcmp(&check[k],&m1,sizeof(m1))) + continue; + if (memcmp(&check[ (k+1)%3 ],&m2,sizeof(m2))) + continue; + + neighbortri[starttri][startv] = j; + neighboredge[starttri][startv] = k; + + neighbortri[j][k] = starttri; + neighboredge[j][k] = startv; + + used[starttri] |= (1 << startv); + used[j] |= (1 << k); + return; + } + } +} + + +/* +================ +StripLength +================ +*/ +int StripLength (int starttri, int startv) +{ + int j; + int k; + + used[starttri] = 2; + + stripverts[0] = (startv)%3; + stripverts[1] = (startv+1)%3; + stripverts[2] = (startv+2)%3; + + striptris[0] = starttri; + striptris[1] = starttri; + striptris[2] = starttri; + stripcount = 3; + + while( 1 ) + { + if (stripcount & 1) + { + j = neighbortri[starttri][(startv+1)%3]; + k = neighboredge[starttri][(startv+1)%3]; + } + else + { + j = neighbortri[starttri][(startv+2)%3]; + k = neighboredge[starttri][(startv+2)%3]; + } + if (j == -1 || used[j]) + goto done; + + stripverts[stripcount] = (k+2)%3; + striptris[stripcount] = j; + stripcount++; + + used[j] = 2; + + starttri = j; + startv = k; + } + +done: + + // clear the temp used flags + for (j=0 ; j<pmesh->numtris ; j++) + if (used[j] == 2) + used[j] = 0; + + return stripcount; +} + +/* +=========== +FanLength +=========== +*/ +int FanLength (int starttri, int startv) +{ + int j; + int k; + + used[starttri] = 2; + + stripverts[0] = (startv)%3; + stripverts[1] = (startv+1)%3; + stripverts[2] = (startv+2)%3; + + striptris[0] = starttri; + striptris[1] = starttri; + striptris[2] = starttri; + stripcount = 3; + + while( 1 ) + { + j = neighbortri[starttri][(startv+2)%3]; + k = neighboredge[starttri][(startv+2)%3]; + + if (j == -1 || used[j]) + goto done; + + stripverts[stripcount] = (k+2)%3; + striptris[stripcount] = j; + stripcount++; + + used[j] = 2; + + starttri = j; + startv = k; + } + +done: + + // clear the temp used flags + for (j=0 ; j<pmesh->numtris ; j++) + if (used[j] == 2) + used[j] = 0; + + return stripcount; +} + + +/* +================ +BuildTris + +Generate a list of trifans or strips +for the model, which holds for all frames +================ +*/ +int numcommandnodes; + +int BuildTris (s_trianglevert_t (*x)[3], s_mesh_t *y, byte **ppdata ) +{ + int i, j, k, m; + int startv; + int len, bestlen, besttype; + int bestverts[MAXSTUDIOTRIANGLES]; + int besttris[MAXSTUDIOTRIANGLES]; + int peak[MAXSTUDIOTRIANGLES]; + int type; + int total = 0; + long t; + int maxlen; + + triangles = x; + pmesh = y; + + + t = time( NULL ); + + for (i=0 ; i<pmesh->numtris ; i++) + { + neighbortri[i][0] = neighbortri[i][1] = neighbortri[i][2] = -1; + used[i] = 0; + peak[i] = pmesh->numtris; + } + + // printf("finding neighbors\n"); + for (i=0 ; i<pmesh->numtris; i++) + { + for (k = 0; k < 3; k++) + { + if (used[i] & (1 << k)) + continue; + + FindNeighbor( i, k ); + } + // printf("%d", used[i] ); + } + // printf("\n"); + + // + // build tristrips + // + numcommandnodes = 0; + numcommands = 0; + memset (used, 0, sizeof(used)); + + for (i=0 ; i<pmesh->numtris ;) + { + // pick an unused triangle and start the trifan + if (used[i]) + { + i++; + continue; + } + + maxlen = 9999; + bestlen = 0; + m = 0; + for (k = i; k < pmesh->numtris && bestlen < 127; k++) + { + int localpeak = 0; + + if (used[k]) + continue; + + if (peak[k] <= bestlen) + continue; + + m++; + for (type = 0 ; type < 2 ; type++) + { + for (startv =0 ; startv < 3 ; startv++) + { + if (type == 1) + len = FanLength (k, startv); + else + len = StripLength (k, startv); + if (len > 127) + { + // skip these, they are too long to encode + } + else if (len > bestlen) + { + besttype = type; + bestlen = len; + for (j=0 ; j<bestlen ; j++) + { + besttris[j] = striptris[j]; + bestverts[j] = stripverts[j]; + } + // printf("%d %d\n", k, bestlen ); + } + if (len > localpeak) + localpeak = len; + } + } + peak[k] = localpeak; + if (localpeak == maxlen) + break; + } + total += (bestlen - 2); + + // printf("%d (%d) %d\n", bestlen, pmesh->numtris - total, i ); + + maxlen = bestlen; + + // mark the tris on the best strip as used + for (j=0 ; j<bestlen ; j++) + used[besttris[j]] = 1; + + if (besttype == 1) + commands[numcommands++] = -bestlen; + else + commands[numcommands++] = bestlen; + + for (j=0 ; j<bestlen ; j++) + { + s_trianglevert_t *tri; + + tri = &triangles[besttris[j]][bestverts[j]]; + + commands[numcommands++] = tri->vertindex; + commands[numcommands++] = tri->normindex; + commands[numcommands++] = tri->s; + commands[numcommands++] = tri->t; + } + // printf("%d ", bestlen - 2 ); + numcommandnodes++; + + if (t != time(NULL)) + { + printf("%2d%%\r", (total * 100) / pmesh->numtris ); + t = time(NULL); + } + } + + commands[numcommands++] = 0; // end of list marker + + *ppdata = (byte *)commands; + + // printf("%d %d %d\n", numcommandnodes, numcommands, pmesh->numtris ); + return numcommands * sizeof( short ); +} + |