예제 #1
0
/*
===========
CG_FreeTrailJunc
===========
*/
void CG_FreeTrailJunc( trailJunc_t *junc )
{
	// kill any juncs after us, so they aren't left hanging
	if (junc->nextJunc)
		CG_KillTrail( junc );

	// make it non-active
	junc->inuse = qfalse;
	junc->freed = qtrue;
	if (junc->nextGlobal)
		junc->nextGlobal->prevGlobal = junc->prevGlobal;
	if (junc->prevGlobal)
		junc->prevGlobal->nextGlobal = junc->nextGlobal;
	if (junc == activeTrails)
		activeTrails = junc->nextGlobal;

	// if it's a head, remove it
	if (junc == headTrails)
		headTrails = junc->nextHead;
	if (junc->nextHead)
		junc->nextHead->prevHead = junc->prevHead;
	if (junc->prevHead)
		junc->prevHead->nextHead = junc->nextHead;
	junc->nextHead = NULL;
	junc->prevHead = NULL;

	// stick it in the free list
	junc->prevGlobal = NULL;
	junc->nextGlobal = freeTrails;
	if (freeTrails)
		freeTrails->prevGlobal = junc;
	freeTrails = junc;

	numTrailsInuse--;
}
예제 #2
0
void CG_AddTrailToScene(trailJunc_t *trail, int iteration, int numJuncs)
{
#define MAX_TRAIL_VERTS     2048
	polyVert_t verts[MAX_TRAIL_VERTS];
	polyVert_t outVerts[MAX_TRAIL_VERTS * 3];
	int k, i, n, l, numOutVerts;
	polyVert_t mid;
	float mod[4];
	float sInc = 0.0f, s = 0.0f;   // TTimo: init
	trailJunc_t *j, *jNext;
	vec3_t fwd, up, p, v;
	(void)fwd; // Ignore compiler warning -- Justasic
	// clipping vars
#define TRAIL_FADE_CLOSE_DIST   64.0
#define TRAIL_FADE_FAR_SCALE    4.0
	vec3_t viewProj;
	float viewDist, fadeAlpha;

	// add spark shader at head position
	if(trail->flags & TJFL_SPARKHEADFLARE)
	{
		j = trail;
		VectorCopy(j->pos, p);
		VectorMA(p, -j->width * 2, vup, p);
		VectorMA(p, -j->width * 2, vright, p);
		VectorCopy(p, verts[0].xyz);
		verts[0].st[0] = 0;
		verts[0].st[1] = 0;
		verts[0].modulate[0] = 255;
		verts[0].modulate[1] = 255;
		verts[0].modulate[2] = 255;
		verts[0].modulate[3] = (unsigned char)(j->alpha * 255.0);

		VectorCopy(j->pos, p);
		VectorMA(p, -j->width * 2, vup, p);
		VectorMA(p, j->width * 2, vright, p);
		VectorCopy(p, verts[1].xyz);
		verts[1].st[0] = 0;
		verts[1].st[1] = 1;
		verts[1].modulate[0] = 255;
		verts[1].modulate[1] = 255;
		verts[1].modulate[2] = 255;
		verts[1].modulate[3] = (unsigned char)(j->alpha * 255.0);

		VectorCopy(j->pos, p);
		VectorMA(p, j->width * 2, vup, p);
		VectorMA(p, j->width * 2, vright, p);
		VectorCopy(p, verts[2].xyz);
		verts[2].st[0] = 1;
		verts[2].st[1] = 1;
		verts[2].modulate[0] = 255;
		verts[2].modulate[1] = 255;
		verts[2].modulate[2] = 255;
		verts[2].modulate[3] = (unsigned char)(j->alpha * 255.0);

		VectorCopy(j->pos, p);
		VectorMA(p,  j->width * 2, vup, p);
		VectorMA(p, -j->width * 2, vright, p);
		VectorCopy(p, verts[3].xyz);
		verts[3].st[0] = 1;
		verts[3].st[1] = 0;
		verts[3].modulate[0] = 255;
		verts[3].modulate[1] = 255;
		verts[3].modulate[2] = 255;
		verts[3].modulate[3] = (unsigned char)(j->alpha * 255.0);

		trap_R_AddPolyToScene(cgs.media.sparkFlareShader, 4, verts);
	}

//	if (trail->flags & TJFL_CROSSOVER && iteration < 1) {
//		iteration = 1;
//	}

	if(!numJuncs)
	{
		// first count the number of juncs in the trail
		j = trail;
		numJuncs = 0;
		sInc = 0;

		while(j)
		{
			numJuncs++;

			// check for a dead next junc
			if(!j->inuse && j->nextJunc && !j->nextJunc->inuse)
			{
				CG_KillTrail(j);
			}
			else if(j->nextJunc && j->nextJunc->freed)
			{
				// not sure how this can happen, but it does, and causes infinite loops
				j->nextJunc = NULL;
			}

			if(j->nextJunc)
			{
				sInc += VectorDistance(j->nextJunc->pos, j->pos);
			}

			j = j->nextJunc;
		}
	}

	if(numJuncs < 2)
	{
		return;
	}

	if(trail->sType == STYPE_STRETCH)
	{
		//sInc = ((1.0 - 0.1) / (float)(numJuncs)); // hack, the end of funnel shows a bit of the start (looping)
		s = 0.05;
		//s = 0.05;
	}
	else if(trail->sType == STYPE_REPEAT)
	{
		s = trail->sTex;
	}

	// now traverse the list
	j = trail;
	jNext = j->nextJunc;
	i = 0;

	while(jNext)
	{

		// first get the directional vectors to the next junc
		VectorSubtract(jNext->pos, j->pos, fwd);
		GetPerpendicularViewVector(cg.refdef.vieworg, j->pos, jNext->pos, up);

		// if it's a crossover, draw it twice
		if(j->flags & TJFL_CROSSOVER)
		{
			if(iteration > 0)
			{
				ProjectPointOntoVector(cg.refdef.vieworg, j->pos, jNext->pos, viewProj);
				VectorSubtract(cg.refdef.vieworg, viewProj, v);
				VectorNormalize(v);

				if(iteration == 1)
				{
					VectorMA(up, 0.3, v, up);
				}
				else
				{
					VectorMA(up, -0.3, v, up);
				}

				VectorNormalize(up);
			}
		}
		// do fading when moving towards the projection point onto the trail segment vector
		else if(!(j->flags & TJFL_NOCULL) && (j->widthEnd > 4 || jNext->widthEnd > 4))
		{
			ProjectPointOntoVector(cg.refdef.vieworg, j->pos, jNext->pos, viewProj);
			viewDist = Distance(viewProj, cg.refdef.vieworg);

			if(viewDist < (TRAIL_FADE_CLOSE_DIST * TRAIL_FADE_FAR_SCALE))
			{
				if(viewDist < TRAIL_FADE_CLOSE_DIST)
				{
					fadeAlpha = 0.0;
				}
				else
				{
					fadeAlpha = (viewDist - TRAIL_FADE_CLOSE_DIST) / (TRAIL_FADE_CLOSE_DIST * TRAIL_FADE_FAR_SCALE);
				}

				if(fadeAlpha < j->alpha)
				{
					j->alpha = fadeAlpha;
				}

				if(fadeAlpha < jNext->alpha)
				{
					jNext->alpha = fadeAlpha;
				}
			}
		}

		// now output the QUAD for this segment

		// 1 ----
		VectorMA(j->pos, 0.5 * j->width, up, p);
		VectorCopy(p, verts[i].xyz);
		verts[i].st[0] = s;
		verts[i].st[1] = 1.0;

		for(k = 0; k < 3; k++)
			verts[i].modulate[k] = (unsigned char)(j->color[k] * 255.0);

		verts[i].modulate[3] = (unsigned char)(j->alpha * 255.0);

		// blend this with the previous junc
		if(j != trail)
		{
			VectorAdd(verts[i].xyz, verts[i - 1].xyz, verts[i].xyz);
			VectorScale(verts[i].xyz, 0.5, verts[i].xyz);
			VectorCopy(verts[i].xyz, verts[i - 1].xyz);
		}
		else if(j->flags & TJFL_FADEIN)
		{
			verts[i].modulate[3] = 0;   // fade in
		}

		i++;

		// 2 ----
		VectorMA(p, -1 * j->width, up, p);
		VectorCopy(p, verts[i].xyz);
		verts[i].st[0] = s;
		verts[i].st[1] = 0.0;

		for(k = 0; k < 3; k++)
			verts[i].modulate[k] = (unsigned char)(j->color[k] * 255.0);

		verts[i].modulate[3] = (unsigned char)(j->alpha * 255.0);

		// blend this with the previous junc
		if(j != trail)
		{
			VectorAdd(verts[i].xyz, verts[i - 3].xyz, verts[i].xyz);
			VectorScale(verts[i].xyz, 0.5, verts[i].xyz);
			VectorCopy(verts[i].xyz, verts[i - 3].xyz);
		}
		else if(j->flags & TJFL_FADEIN)
		{
			verts[i].modulate[3] = 0;   // fade in
		}

		i++;

		if(trail->sType == STYPE_REPEAT)
		{
			s = jNext->sTex;
		}
		else
		{
			//s += sInc;
			s += VectorDistance(j->pos, jNext->pos) / sInc;

			if(s > 1.0)
			{
				s = 1.0;
			}
		}

		// 3 ----
		VectorMA(jNext->pos, -0.5 * jNext->width, up, p);
		VectorCopy(p, verts[i].xyz);
		verts[i].st[0] = s;
		verts[i].st[1] = 0.0;

		for(k = 0; k < 3; k++)
			verts[i].modulate[k] = (unsigned char)(jNext->color[k] * 255.0);

		verts[i].modulate[3] = (unsigned char)(jNext->alpha * 255.0);
		i++;

		// 4 ----
		VectorMA(p, jNext->width, up, p);
		VectorCopy(p, verts[i].xyz);
		verts[i].st[0] = s;
		verts[i].st[1] = 1.0;

		for(k = 0; k < 3; k++)
			verts[i].modulate[k] = (unsigned char)(jNext->color[k] * 255.0);

		verts[i].modulate[3] = (unsigned char)(jNext->alpha * 255.0);
		i++;

		if(i + 4 > MAX_TRAIL_VERTS)
		{
			break;
		}

		j = jNext;
		jNext = j->nextJunc;
	}

	if(trail->flags & TJFL_FIXDISTORT)
	{
		// build the list of outVerts, by dividing up the QUAD's into 4 Tri's each, so as to allow
		//  any shaped (convex) Quad without bilinear distortion
		for(k = 0, numOutVerts = 0; k < i; k += 4)
		{
			VectorCopy(verts[k].xyz, mid.xyz);
			mid.st[0] = verts[k].st[0];
			mid.st[1] = verts[k].st[1];

			for(l = 0; l < 4; l++)
			{
				mod[l] = (float)verts[k].modulate[l];
			}

			for(n = 1; n < 4; n++)
			{
				VectorAdd(verts[k + n].xyz, mid.xyz, mid.xyz);
				mid.st[0] += verts[k + n].st[0];
				mid.st[1] += verts[k + n].st[1];

				for(l = 0; l < 4; l++)
				{
					mod[l] += (float)verts[k + n].modulate[l];
				}
			}

			VectorScale(mid.xyz, 0.25, mid.xyz);
			mid.st[0] *= 0.25;
			mid.st[1] *= 0.25;

			for(l = 0; l < 4; l++)
			{
				mid.modulate[l] = (unsigned char)(mod[l] / 4.0);
			}

			// now output the tri's
			for(n = 0; n < 4; n++)
			{
				outVerts[numOutVerts++] = verts[k + n];
				outVerts[numOutVerts++] = mid;

				if(n < 3)
				{
					outVerts[numOutVerts++] = verts[k + n + 1];
				}
				else
				{
					outVerts[numOutVerts++] = verts[k];
				}
			}

		}

		if(!(trail->flags & TJFL_NOPOLYMERGE))
		{
			trap_R_AddPolysToScene(trail->shader, 3, &outVerts[0], numOutVerts / 3);
		}
		else
		{
			int k;

			for(k = 0; k < numOutVerts / 3; k++)
			{
				trap_R_AddPolyToScene(trail->shader, 3, &outVerts[k * 3]);
			}
		}
	}
	else
	{
		// send the polygons
		// FIXME: is it possible to send a GL_STRIP here? We are actually sending 2x the verts we really need to
		if(!(trail->flags & TJFL_NOPOLYMERGE))
		{
			trap_R_AddPolysToScene(trail->shader, 4, &verts[0], i / 4);
		}
		else
		{
			int k;

			for(k = 0; k < i / 4; k++)
			{
				trap_R_AddPolyToScene(trail->shader, 4, &verts[k * 4]);
			}
		}
	}

	// do we need to make another pass?
	if(trail->flags & TJFL_CROSSOVER)
	{
		if(iteration < 2)
		{
			CG_AddTrailToScene(trail, iteration + 1, numJuncs);
		}
	}

}