Пример #1
0
/*
================
BuildTris

Generate a list of trifans or strips
for the model, which holds for all frames
================
*/
void BuildTris (void)
{
	int		i, j, k;
	int		startv;
	float	s, t;
	int		len, bestlen, besttype;
	int		bestverts[1024];
	int		besttris[1024];
	int		type;

	//
	// build tristrips
	//
	numorder = 0;
	numcommands = 0;
	memset (used, 0, sizeof(used));
	for (i = 0; i < pheader->numtris; i++)
	{
		// pick an unused triangle and start the trifan
		if (used[i])
			continue;

		bestlen = 0;
		besttype = 0;
		for (type = 0 ; type < 2 ; type++)
//	type = 1;
		{
			for (startv = 0; startv < 3; startv++)
			{
				if (type == 1)
					len = StripLength (i, startv);
				else
					len = FanLength (i, startv);
				if (len > bestlen)
				{
					besttype = type;
					bestlen = len;
					for (j = 0; j < bestlen+2; j++)
						bestverts[j] = stripverts[j];
					for (j = 0; j < bestlen; j++)
						besttris[j] = striptris[j];
				}
			}
		}

		// 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+2);
		else
			commands[numcommands++] = -(bestlen+2);

		for (j = 0; j < bestlen+2; j++)
		{
			int		tmp;

			// emit a vertex into the reorder buffer
			k = bestverts[j];
			vertexorder[numorder++] = k;

			// emit s/t coords into the commands stream
			s = stverts[k].s;
			t = stverts[k].t;
			if (!triangles[besttris[0]].facesfront && stverts[k].onseam)
				s += pheader->skinwidth / 2;	// on back side
			s = (s + 0.5) / pheader->skinwidth;
			t = (t + 0.5) / pheader->skinheight;

		//	*(float *)&commands[numcommands++] = s;
		//	*(float *)&commands[numcommands++] = t;
			// NOTE: 4 == sizeof(int)
			//	   == sizeof(float)
			memcpy (&tmp, &s, 4);
			commands[numcommands++] = tmp;
			memcpy (&tmp, &t, 4);
			commands[numcommands++] = tmp;
		}
	}

	commands[numcommands++] = 0;		// end of list marker

	Con_DPrintf2 ("%3i tri %3i vert %3i cmd\n", pheader->numtris, numorder, numcommands);

	allverts += numorder;
	alltris += pheader->numtris;
}
Пример #2
0
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 );
}
Пример #3
0
/*
	BuildTris

	Generate a list of trifans or strips
	for the model, which holds for all frames
*/
static void
BuildTris (void)
{
	float		s, t;
	int			bestlen, len, startv, type, i, j, k;
	int			besttype = 0;
	int		   *bestverts = 0, *besttris = 0;

	// build tristrips
	numorder = 0;
	numcommands = 0;
	stripcount = 0;
	alloc_used (pheader->mdl.numtris);
	memset (used, 0, used_size * sizeof (used[0]));

	for (i = 0; i < pheader->mdl.numtris; i++) {
		// pick an unused triangle and start the trifan
		if (used[i])
			continue;

		bestlen = 0;
		for (type = 0; type < 2; type++) {
//  type = 1;
			for (startv = 0; startv < 3; startv++) {
				if (type == 1)
					len = StripLength (i, startv);
				else
					len = FanLength (i, startv);
				if (len > bestlen) {
					besttype = type;
					bestlen = len;
					if (bestverts)
						free (bestverts);
					if (besttris)
						free (besttris);
					bestverts = stripverts;
					besttris = striptris;
					stripverts = striptris = 0;
					strip_size = 0;
				}
			}
		}

		// mark the tris on the best strip as used
		for (j = 0; j < bestlen; j++)
			used[besttris[j + 2]] = 1;

		if (besttype == 1)
			add_command (bestlen + 2);
		else
			add_command (-(bestlen + 2));

		for (j = 0; j < bestlen + 2; j++) {
			int         tmp;
			// emit a vertex into the reorder buffer
			k = bestverts[j];
			add_vertex (k);

			// emit s/t coords into the commands stream
			s = stverts[k].s;
			t = stverts[k].t;
			if (!triangles[besttris[0]].facesfront && stverts[k].onseam)
				s += pheader->mdl.skinwidth / 2;	// on back side
			s = (s + 0.5) / pheader->mdl.skinwidth;
			t = (t + 0.5) / pheader->mdl.skinheight;

			memcpy (&tmp, &s, 4);
			add_command (tmp);
			memcpy (&tmp, &t, 4);
			add_command (tmp);
		}
	}

	add_command (0);					// end of list marker

	Sys_MaskPrintf (SYS_DEV, "%3i tri %3i vert %3i cmd\n",
					pheader->mdl.numtris, numorder, numcommands);

	allverts += numorder;
	alltris += pheader->mdl.numtris;

	if (bestverts)
		free (bestverts);
	if (besttris)
		free (besttris);
}
Пример #4
0
/*
================
BuildTris

Generate a list of trifans or strips
for the model, which holds for all frames
================
*/
void BuildTris (void)
{
	int		i, j, k;
	int		startv;
	mtriangle_t	*last, *check;
	int		m1, m2;
	int		striplength;
	trivertx_t	*v;
	mtriangle_t *tv;
	float	s, t;
	int		index;
	int		len, bestlen, besttype;
	int*		bestverts = Sys_BigStackAlloc(1024 * sizeof(int), "BuildTris");
	int*		besttris = Sys_BigStackAlloc(1024 * sizeof(int), "BuildTris");
	int		type;

	//
	// build tristrips
	//
	numorder = 0;
	numcommands = 0;
	memset (used, 0, sizeof(used));
	for (i=0 ; i<pheader->numtris ; i++)
	{
		// pick an unused triangle and start the trifan
		if (used[i])
			continue;

		bestlen = 0;
		for (type = 0 ; type < 2 ; type++)
//	type = 1;
		{
			for (startv =0 ; startv < 3 ; startv++)
			{
				if (type == 1)
					len = StripLength (i, startv);
				else
					len = FanLength (i, startv);
				if (len > bestlen)
				{
					besttype = type;
					bestlen = len;
					for (j=0 ; j<bestlen+2 ; j++)
						bestverts[j] = stripverts[j];
					for (j=0 ; j<bestlen ; j++)
						besttris[j] = striptris[j];
				}
			}
		}

		// 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+2);
		else
			commands[numcommands++] = -(bestlen+2);

		for (j=0 ; j<bestlen+2 ; j++)
		{
			// emit a vertex into the reorder buffer
			k = bestverts[j];
			vertexorder[numorder++] = k;

			// emit s/t coords into the commands stream
			s = stverts[k].s;
			t = stverts[k].t;
			if (!triangles[besttris[0]].facesfront && stverts[k].onseam)
				s += pheader->skinwidth / 2;	// on back side
			s = (s + 0.5) / pheader->skinwidth;
			t = (t + 0.5) / pheader->skinheight;

			*(float *)&commands[numcommands++] = s;
			*(float *)&commands[numcommands++] = t;
		}
	}

	commands[numcommands++] = 0;		// end of list marker

	Con_DPrintf ("%3i tri %3i vert %3i cmd\n", pheader->numtris, numorder, numcommands);

	allverts += numorder;
	alltris += pheader->numtris;
	Sys_BigStackFree(1024 * sizeof(int) + 1024 * sizeof(int), "BuildTris");
}
Пример #5
0
static int BuildOptimizedList( int mesh[][3], int strip[][3], int numInputTris ){
	int t;
	int stripLen = 0;
	int startTri = -1;
	int bestTri = -1, bestLength = 0, bestOrientation = -1;
	int matchedSides = 0;
	int orientation = 0;
	int seedTriangles[MAX_MATCHED_SIDES][MAX_SEED_TRIANGLES];
	int seedLengths[MAX_ORIENTATIONS][MAX_MATCHED_SIDES][MAX_SEED_TRIANGLES];
	int numSeeds[MAX_MATCHED_SIDES] = { 0, 0, 0 };
	int i;

	// build a ranked list of candidate seed triangles based on
	// number of offshoot strips.  Precedence goes to orphans,
	// then corners, then edges, and interiors.
	memset( seedTriangles, 0xff, sizeof( seedTriangles ) );
	memset( seedLengths, 0xff, sizeof( seedLengths ) );

	for ( i = 0; i < MAX_MATCHED_SIDES; i++ )
	{
		// find the triangle with lowest number of child strips
		for ( t = 0; t < numInputTris; t++ )
		{
			int orientation;
			int n;

			if ( s_used[t] ) {
				continue;
			}

			// try the candidate triangle in three different orientations
			matchedSides = 0;
			for ( orientation = 0; orientation < 3; orientation++ )
			{
				if ( ( n = FindNextTriangleInStripOrFan( mesh, t, orientation, numInputTris, 1 ) ) != -1 ) {
					matchedSides++;
				}
			}

			if ( matchedSides == i ) {
				seedTriangles[i][numSeeds[i]] = t;
				numSeeds[i]++;
				if ( numSeeds[i] == MAX_SEED_TRIANGLES ) {
					break;
				}
			}
		}
	}

	// we have a list of potential seed triangles, so we now go through each
	// potential candidate and look to see which produces the longest strip
	// and select our startTri based on this
	for ( i = 0; i < MAX_MATCHED_SIDES; i++ )
	{
		int j;

		for ( j = 0; j < numSeeds[i]; j++ )
		{
			for ( orientation = 0; orientation < 3; orientation++ )
			{
				int k;

				seedLengths[orientation][i][j] = StripLength( mesh, strip, seedTriangles[i][j], orientation, numInputTris, 2 );

				if ( seedLengths[orientation][i][j] > bestLength ) {
					bestTri = seedTriangles[i][j];
					bestLength = seedLengths[orientation][i][j];
					bestOrientation = orientation;
				}

				for ( k = 0; k < numInputTris; k++ )
				{
					if ( s_used[k] == 2 ) {
						s_used[k] = 0;
					}
				}
			}
		}

		if ( bestTri != -1 ) {
			break;
		}
	}

	// build the strip for real
	if ( bestTri != -1 ) {
		stripLen = StripLength( mesh, strip, bestTri, bestOrientation, numInputTris, 1 );
	}

	return stripLen;
}
Пример #6
0
/*
================
BuildGlCmds

Generate a list of trifans or strips
for the model, which holds for all frames
================
*/
static void BuildGlCmds (void)
{
	int		i, j, k;
	int		startv;
	float	s, t;
	int		len, bestlen, besttype;
	int		best_xyz[1024];
	int		best_st[1024];
	int		best_tris[1024];
	int		type;

	//
	// build tristrips
	//
	numcommands = 0;
	numglverts = 0;
	memset (used, 0, sizeof(used));
	for (i=0 ; i<model.num_tris ; i++)
	{
		// pick an unused triangle and start the trifan
		if (used[i])
			continue;

		bestlen = 0;
		for (type = 0 ; type < 2 ; type++)
//	type = 1;
		{
			for (startv =0 ; startv < 3 ; startv++)
			{
				if (type == 1)
					len = StripLength (i, startv);
				else
					len = FanLength (i, startv);
				if (len > bestlen)
				{
					besttype = type;
					bestlen = len;
					for (j=0 ; j<bestlen+2 ; j++)
					{
						best_st[j] = strip_st[j];
						best_xyz[j] = strip_xyz[j];
					}
					for (j=0 ; j<bestlen ; j++)
						best_tris[j] = strip_tris[j];
				}
			}
		}

		// mark the tris on the best strip/fan as used
		for (j=0 ; j<bestlen ; j++)
			used[best_tris[j]] = 1;

		if (besttype == 1)
			commands[numcommands++] = (bestlen+2);
		else
			commands[numcommands++] = -(bestlen+2);

		numglverts += bestlen+2;

		for (j=0 ; j<bestlen+2 ; j++)
		{
			// emit a vertex into the reorder buffer
			k = best_st[j];

			// emit s/t coords into the commands stream
			s = base_st[k].s;
			t = base_st[k].t;

			s = (s + 0.5) / model.skinwidth;
			t = (t + 0.5) / model.skinheight;

			*(float *)&commands[numcommands++] = s;
			*(float *)&commands[numcommands++] = t;
			*(int *)&commands[numcommands++] = best_xyz[j];
		}
	}

	commands[numcommands++] = 0;		// end of list marker
}
Пример #7
0
/*
================
BuildTris

Generate a list of trifans or strips
for the model, which holds for all frames
================
*/
void BuildTris (void)
{
	int		i, j, k;
	int		startv;
	mtriangle_t	*last, *check;
	int		m1, m2;
	int		striplength;
	trivertx_t	*v;
	mtriangle_t	*tv;
	float		s, t;
	int		index;
	int		len, bestlen, besttype;
	int		bestverts[1024];
	int		besttris[1024];
	int		type;
	int		stripmax = 0;

	//
	// build tristrips
	//
	numorder = 0;
	numcommands = 0;
	memset (used, 0, sizeof(used));
	for (i=0 ; i<pheader->numtris ; i++)
	{
		// pick an unused triangle and start the trifan
		if (used[i])
			continue;

		bestlen = 0;
		for (type = 0 ; type < 2 ; type++)
//	type = 1;
		{
			for (startv =0 ; startv < 3 ; startv++)
			{
				if (type == 1)
					len = StripLength (i, startv);
				else
					len = FanLength (i, startv);
				
				// Save peak
				if (len > stripmax)
					stripmax = len;

				if (len > bestlen)
				{
					besttype = type;
					bestlen = len;
					for (j=0 ; j<bestlen+2 ; j++)
						bestverts[j] = stripverts[j];
					for (j=0 ; j<bestlen ; j++)
						besttris[j] = striptris[j];
				}
			}
		}

		// mark the tris on the best strip as used
		for (j=0 ; j<bestlen ; j++)
			used[besttris[j]] = 1;

		ChkCmds ("BuildTris");

		if (besttype == 1)
			commands[numcommands++] = (bestlen+2);
		else
			commands[numcommands++] = -(bestlen+2);

		for (j=0 ; j<bestlen+2 ; j++)
		{
			// emit a vertex into the reorder buffer
			k = bestverts[j];
			vertexorder[numorder++] = k;

			// emit s/t coords into the commands stream
			s = stverts[k].s;
			t = stverts[k].t;
			if (!triangles[besttris[0]].facesfront && stverts[k].onseam)
				s += pheader->skinwidth / 2;	// on back side
			s = (s + 0.5) / pheader->skinwidth;
			t = (t + 0.5) / pheader->skinheight;

			ChkCmds ("BuildTris");

			*(float *)&commands[numcommands++] = s;
			*(float *)&commands[numcommands++] = t;
		}
	}

	ChkCmds ("BuildTris");

	commands[numcommands++] = 0;		// end of list marker

	// Check old limit
	if (stripmax + 2 >= 128)
	{
		Con_Printf ("\002BuildTris: ");
		Con_Printf ("excessive stripcount (%d, normal max = %d) in %s\n", stripmax, 128 - 2, aliasmodel->name);
	}

	// Check old limit
	if (numcommands >= 8192)
	{
		Con_Printf ("\002BuildTris: ");
		Con_Printf ("excessive commands (%d, normal max = %d) in %s\n", numcommands, 8192, aliasmodel->name);
	}

#ifndef NO_CACHE_MESH
	Con_DPrintf ("%3i tri %3i vert %3i cmd\n", pheader->numtris, numorder, numcommands);
#endif
}