mirror of
https://github.com/nillerusr/source-engine.git
synced 2026-08-08 09:49:36 +00:00
1
This commit is contained in:
@@ -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 );
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user