Пример #1
0
void CG_AddMarks()
{
	int        j;
	markPoly_t *mp, *next;
	int        t;
	int        fade;

	if ( !cg_addMarks.integer )
	{
		return;
	}

	mp = cg_activeMarkPolys.nextMark;

	for ( ; mp != &cg_activeMarkPolys; mp = next )
	{
		// grab next now, so if the local entity is freed we
		// still have it
		next = mp->nextMark;

		// see if it is time to completely remove it
		if ( cg.time > mp->time + MARK_TOTAL_TIME )
		{
			CG_FreeMarkPoly( mp );
			continue;
		}

		// fade all marks out with time
		t = mp->time + MARK_TOTAL_TIME - cg.time;

		if ( t < MARK_FADE_TIME )
		{
			fade = 255 * t / MARK_FADE_TIME;

			if ( mp->alphaFade )
			{
				for ( j = 0; j < mp->poly.numVerts; j++ )
				{
					mp->verts[ j ].modulate[ 3 ] = fade;
				}
			}
			else
			{
				for ( j = 0; j < mp->poly.numVerts; j++ )
				{
					mp->verts[ j ].modulate[ 0 ] = mp->color[ 0 ] * fade;
					mp->verts[ j ].modulate[ 1 ] = mp->color[ 1 ] * fade;
					mp->verts[ j ].modulate[ 2 ] = mp->color[ 2 ] * fade;
				}
			}
		}
		trap_R_AddPolyToScene( mp->markShader, mp->poly.numVerts, mp->verts );
	}
}
Пример #2
0
/*
=======================================================================================================================================
CG_EmitPolyVerts
=======================================================================================================================================
*/
static void CG_EmitPolyVerts(const refEntity_t *re) {
	polyVert_t verts[4];
	float sinR, cosR;
	float angle;
	vec3_t left, up;
	int i;

	if (re->rotation) {
		angle = M_PI * re->rotation / 180.0;
		sinR = sin(angle);
		cosR = cos(angle);

		VectorScale(cg.refdef.viewaxis[1], cosR * re->radius, left);
		VectorMA(left, -sinR * re->radius, cg.refdef.viewaxis[2], left);
		VectorScale(cg.refdef.viewaxis[2], cosR * re->radius, up);
		VectorMA(up, sinR * re->radius, cg.refdef.viewaxis[1], up);
	} else {
		VectorScale(cg.refdef.viewaxis[1], re->radius, left);
		VectorScale(cg.refdef.viewaxis[2], re->radius, up);
	}

	verts[0].xyz[0] = re->origin[0] + left[0] + up[0];
	verts[0].xyz[1] = re->origin[1] + left[1] + up[1];
	verts[0].xyz[2] = re->origin[2] + left[2] + up[2];
	verts[0].st[0] = 0.0;
	verts[0].st[1] = 0.0;

	verts[1].xyz[0] = re->origin[0] - left[0] + up[0];
	verts[1].xyz[1] = re->origin[1] - left[1] + up[1];
	verts[1].xyz[2] = re->origin[2] - left[2] + up[2];
	verts[1].st[0] = 1.0;
	verts[1].st[1] = 0.0;

	verts[2].xyz[0] = re->origin[0] - left[0] - up[0];
	verts[2].xyz[1] = re->origin[1] - left[1] - up[1];
	verts[2].xyz[2] = re->origin[2] - left[2] - up[2];
	verts[2].st[0] = 1.0;
	verts[2].st[1] = 1.0;

	verts[3].xyz[0] = re->origin[0] + left[0] - up[0];
	verts[3].xyz[1] = re->origin[1] + left[1] - up[1];
	verts[3].xyz[2] = re->origin[2] + left[2] - up[2];
	verts[3].st[0] = 0.0;
	verts[3].st[1] = 1.0;

	for (i = 0; i < 4; i++) {
		verts[i].modulate[0] = re->shaderRGBA[0];
		verts[i].modulate[1] = re->shaderRGBA[1];
		verts[i].modulate[2] = re->shaderRGBA[2];
		verts[i].modulate[3] = re->shaderRGBA[3];
	}

	trap_R_AddPolyToScene(re->customShader, 4, verts, 0, 0);
}
Пример #3
0
/*
===============
CG_AddMarks
===============
*/
void CG_AddMarks(void)
{
	int        j;
	markPoly_t *mp, *next;
	int        t;
	int        fade;

	if (!cg_markTime.integer)
	{
		return;
	}

	mp = cg_activeMarkPolys.nextMark;
	for ( ; mp != &cg_activeMarkPolys ; mp = next)
	{
		// grab next now, so if the local entity is freed we
		// still have it
		next = mp->nextMark;

		// see if it is time to completely remove it
		if (cg.time > mp->time + mp->duration)
		{
			CG_FreeMarkPoly(mp);
			continue;
		}

		// fade all marks out with time
		t = mp->time + mp->duration - cg.time;
		if (t < (float)mp->duration / 2.0)
		{
			fade = (int)(255.0 * (float)t / ((float)mp->duration / 2.0));
			if (mp->alphaFade)
			{
				for (j = 0 ; j < mp->poly.numVerts ; j++)
				{
					mp->verts[j].modulate[3] = fade;
				}
			}
			else
			{
				for (j = 0 ; j < mp->poly.numVerts ; j++)
				{
					mp->verts[j].modulate[0] = mp->color[0] * fade;
					mp->verts[j].modulate[1] = mp->color[1] * fade;
					mp->verts[j].modulate[2] = mp->color[2] * fade;
				}
			}
		}

		trap_R_AddPolyToScene(mp->markShader, mp->poly.numVerts, mp->verts);
	}
}
Пример #4
0
void CG_EffectMark(qhandle_t markShader, const vec3_t origin, const vec3_t dir, float alpha, float radius)
{
	// 'quick' version of the CG_ImpactMark function

	vec3_t axis[3], originalPoints[4];
	float texCoordScale;
	byte colors[4];
	int i;
	polyVert_t *v, verts[4];

	if (!cg_addMarks.integer) {
		return;
	}

	if (radius <= 0) {
		CG_Error("CG_EffectMark called with <= 0 radius");
	}
	// create the texture axis
	VectorNormalize2(dir, axis[0]);
	PerpendicularVector(axis[1], axis[0]);
	VectorSet(axis[2], 1, 0, 0);	// This is _wrong_, but the function is for water anyway (i.e. usually flat)
	CrossProduct(axis[0], axis[2], axis[1]);

	texCoordScale = 0.5 * 1.0 / radius;

	// create the full polygon
	for (i = 0; i < 3; i++) {
		originalPoints[0][i] = origin[i] - radius * axis[1][i] - radius * axis[2][i];
		originalPoints[1][i] = origin[i] + radius * axis[1][i] - radius * axis[2][i];
		originalPoints[2][i] = origin[i] + radius * axis[1][i] + radius * axis[2][i];
		originalPoints[3][i] = origin[i] - radius * axis[1][i] + radius * axis[2][i];
	}

	colors[0] = 127;
	colors[1] = 127;
	colors[2] = 127;
	colors[3] = alpha * 255;

	for (i = 0, v = verts; i < 4; i++, v++) {
		vec3_t delta;

		VectorCopy(originalPoints[i], v->xyz);
		VectorSubtract(v->xyz, origin, delta);
		v->st[0] = 0.5 + DotProduct(delta, axis[1]) * texCoordScale;
		v->st[1] = 0.5 + DotProduct(delta, axis[2]) * texCoordScale;
		*(int *) v->modulate = *(int *) colors;
	}

	trap_R_AddPolyToScene(markShader, 4, verts);
}
Пример #5
0
/*
* CG_AddDecals
*/
void CG_AddDecals( void )
{
	int i;
	float fade;
	cdecal_t *dl, *next, *hnode;
	poly_t *poly;
	byte_vec4_t color;

	// add decals in first-spawed - first-drawn order
	hnode = &cg_decals_headnode;
	for( dl = hnode->prev; dl != hnode; dl = next )
	{
		next = dl->prev;

		// it's time to DIE
		if( dl->die <= cg.time )
		{
			CG_FreeDecal( dl );
			continue;
		}
		poly = dl->poly;

		// fade out
		if( dl->fadetime < cg.time )
		{
			fade = ( dl->die - cg.time ) * dl->fadefreq;

			if( dl->fadealpha )
			{
				color[0] = ( qbyte )( dl->color[0] );
				color[1] = ( qbyte )( dl->color[1] );
				color[2] = ( qbyte )( dl->color[2] );
				color[3] = ( qbyte )( dl->color[3] * fade );
			}
			else
			{
				color[0] = ( qbyte )( dl->color[0] * fade );
				color[1] = ( qbyte )( dl->color[1] * fade );
				color[2] = ( qbyte )( dl->color[2] * fade );
				color[3] = ( qbyte )( dl->color[3] );
			}

			for( i = 0; i < poly->numverts; i++ )
				*( int * )poly->colors[i] = *( int * )color;
		}

		trap_R_AddPolyToScene( poly );
	}
}
Пример #6
0
/*
* CG_Addpolys
*/
void CG_AddPolys( void )
{
	int i;
	float fade;
	cpoly_t	*cgpoly, *next, *hnode;
	poly_t *poly;
	static vec3_t angles;

	// add polys in first-spawned - first-drawn order
	hnode = &cg_polys_headnode;
	for( cgpoly = hnode->prev; cgpoly != hnode; cgpoly = next )
	{
		next = cgpoly->prev;

		// it's time to die
		if( cgpoly->die <= cg.time )
		{
			CG_FreePoly( cgpoly );
			continue;
		}

		poly = cgpoly->poly;

		for( i = 0; i < poly->numverts; i++ )
			VectorCopy( cgpoly->verts[i], poly->verts[i] );
		for( i = 0; i < 3; i++ )
			angles[i] = anglemod( cgpoly->angles[i] );

		CG_OrientPolygon( cgpoly->origin, angles, poly );

		// fade out
		if( cgpoly->fadetime < cg.time )
		{
			fade = ( cgpoly->die - cg.time ) * cgpoly->fadefreq;

			for( i = 0; i < poly->numverts; i++ )
			{
				poly->colors[i][0] = ( uint8_t )( cgpoly->color[0] * fade * 255 );
				poly->colors[i][1] = ( uint8_t )( cgpoly->color[1] * fade * 255 );
				poly->colors[i][2] = ( uint8_t )( cgpoly->color[2] * fade * 255 );
				poly->colors[i][3] = ( uint8_t )( cgpoly->color[3] * fade * 255 );
			}
		}

		trap_R_AddPolyToScene( poly );
	}
}
Пример #7
0
/*
===============
CG_DrawPlane

Draw a quad in 3 space - basically CG_DrawPic in 3 space
===============
*/
void CG_DrawPlane( vec3_t origin, vec3_t down, vec3_t right, qhandle_t shader )
{
	polyVert_t verts[ 4 ];
	vec3_t     temp;

	VectorCopy( origin, 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 ] = 255;

	VectorAdd( origin, right, temp );
	VectorCopy( temp, verts[ 1 ].xyz );
	verts[ 1 ].st[ 0 ] = 1;
	verts[ 1 ].st[ 1 ] = 0;
	verts[ 1 ].modulate[ 0 ] = 255;
	verts[ 1 ].modulate[ 1 ] = 255;
	verts[ 1 ].modulate[ 2 ] = 255;
	verts[ 1 ].modulate[ 3 ] = 255;

	VectorAdd( origin, right, temp );
	VectorAdd( temp, down, temp );
	VectorCopy( temp, 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 ] = 255;

	VectorAdd( origin, down, temp );
	VectorCopy( temp, verts[ 3 ].xyz );
	verts[ 3 ].st[ 0 ] = 0;
	verts[ 3 ].st[ 1 ] = 1;
	verts[ 3 ].modulate[ 0 ] = 255;
	verts[ 3 ].modulate[ 1 ] = 255;
	verts[ 3 ].modulate[ 2 ] = 255;
	verts[ 3 ].modulate[ 3 ] = 255;

	trap_R_AddPolyToScene( shader, 4, verts );
}
Пример #8
0
/*
===============
CG_DrawSurfNormal

Draws a vector against
the surface player is looking at
===============
*/
static void CG_DrawSurfNormal( void )
{
	trace_t    tr;
	vec3_t     end, temp;
	polyVert_t normal[ 4 ];
	vec4_t     color = { 0.0f, 255.0f, 0.0f, 128.0f };

	VectorMA( cg.refdef.vieworg, 8192, cg.refdef.viewaxis[ 0 ], end );

	CG_Trace( &tr, cg.refdef.vieworg, NULL, NULL, end, cg.predictedPlayerState.clientNum,
	          MASK_SOLID, 0 );

	VectorCopy( tr.endpos, normal[ 0 ].xyz );
	normal[ 0 ].st[ 0 ] = 0;
	normal[ 0 ].st[ 1 ] = 0;
	Vector4Copy( color, normal[ 0 ].modulate );

	VectorMA( tr.endpos, NORMAL_WIDTH, cg.refdef.viewaxis[ 1 ], temp );
	VectorCopy( temp, normal[ 1 ].xyz );
	normal[ 1 ].st[ 0 ] = 0;
	normal[ 1 ].st[ 1 ] = 1;
	Vector4Copy( color, normal[ 1 ].modulate );

	VectorMA( tr.endpos, NORMAL_HEIGHT, tr.plane.normal, temp );
	VectorMA( temp, NORMAL_WIDTH, cg.refdef.viewaxis[ 1 ], temp );
	VectorCopy( temp, normal[ 2 ].xyz );
	normal[ 2 ].st[ 0 ] = 1;
	normal[ 2 ].st[ 1 ] = 1;
	Vector4Copy( color, normal[ 2 ].modulate );

	VectorMA( tr.endpos, NORMAL_HEIGHT, tr.plane.normal, temp );
	VectorCopy( temp, normal[ 3 ].xyz );
	normal[ 3 ].st[ 0 ] = 1;
	normal[ 3 ].st[ 1 ] = 0;
	Vector4Copy( color, normal[ 3 ].modulate );

	trap_R_AddPolyToScene( cgs.media.outlineShader, 4, normal );
}
Пример #9
0
/*
===================
CG_Aura_DrawSpike
===================
  Draws the polygons for one aura spike
*/
static void CG_Aura_DrawSpike (vec3_t start, vec3_t end, float width, qhandle_t shader, vec4_t RGBModulate){
	vec3_t line, offset, viewLine;
	polyVert_t verts[4];
	float len;
	int i, j;
	
	VectorSubtract (end, start, line);
	VectorSubtract (start, cg.refdef.vieworg, viewLine);
	CrossProduct (viewLine, line, offset);
	len = VectorNormalize (offset);
	
	if (!len){
		return;
	}
	
	VectorMA (end, -width, offset, verts[0].xyz);
	verts[0].st[0] = 1;
	verts[0].st[1] = 0;
	VectorMA (end, width, offset, verts[1].xyz);
	verts[1].st[0] = 0;
	verts[1].st[1] = 0;
	VectorMA (start, width, offset, verts[2].xyz);
	verts[2].st[0] = 0;
	verts[2].st[1] = 1;
	VectorMA (start, -width, offset, verts[3].xyz);
	verts[3].st[0] = 1;
	verts[3].st[1] = 1;
	
	for (i = 0;i < 4;i++){
		for (j = 0;j < 4;j++){
			verts[i].modulate[j] = 255 * RGBModulate[j];
		}
	}

	trap_R_AddPolyToScene( shader, 4, verts);
}
Пример #10
0
/*
* CG_AddFragmentedDecal
*/
void CG_AddFragmentedDecal( vec3_t origin, vec3_t dir, float orient, float radius,
							float r, float g, float b, float a, struct shader_s *shader ) {
	int i, j, c;
	vec3_t axis[3];
	byte_vec4_t color;
	fragment_t *fr, fragments[MAX_TEMPDECAL_FRAGMENTS];
	int numfragments;
	poly_t poly;
	vec4_t verts[MAX_BLOBSHADOW_VERTS];
	static vec4_t t_verts[MAX_TEMPDECAL_VERTS * MAX_TEMPDECALS];
	static vec4_t t_norms[MAX_TEMPDECAL_VERTS * MAX_TEMPDECALS];
	static vec2_t t_stcoords[MAX_TEMPDECAL_VERTS * MAX_TEMPDECALS];
	static byte_vec4_t t_colors[MAX_TEMPDECAL_VERTS * MAX_TEMPDECALS];

	if( radius <= 0 || VectorCompare( dir, vec3_origin ) ) {
		return; // invalid

	}

	// calculate orientation matrix
	VectorNormalize2( dir, axis[0] );
	PerpendicularVector( axis[1], axis[0] );
	RotatePointAroundVector( axis[2], axis[0], axis[1], orient );
	CrossProduct( axis[0], axis[2], axis[1] );

	numfragments = trap_R_GetClippedFragments( origin, radius, axis, // clip it
											   MAX_BLOBSHADOW_VERTS, verts, MAX_TEMPDECAL_FRAGMENTS, fragments );

	// no valid fragments
	if( !numfragments ) {
		return;
	}

	// clamp and scale colors
	if( r < 0 ) {
		r = 0;
	} else if( r > 1 ) {
		r = 255;
	} else {
		r *= 255;
	}
	if( g < 0 ) {
		g = 0;
	} else if( g > 1 ) {
		g = 255;
	} else {
		g *= 255;
	}
	if( b < 0 ) {
		b = 0;
	} else if( b > 1 ) {
		b = 255;
	} else {
		b *= 255;
	}
	if( a < 0 ) {
		a = 0;
	} else if( a > 1 ) {
		a = 255;
	} else {
		a *= 255;
	}

	color[0] = ( uint8_t )( r );
	color[1] = ( uint8_t )( g );
	color[2] = ( uint8_t )( b );
	color[3] = ( uint8_t )( a );
	c = *( int * )color;

	radius = 0.5f / radius;
	VectorScale( axis[1], radius, axis[1] );
	VectorScale( axis[2], radius, axis[2] );

	memset( &poly, 0, sizeof( poly ) );

	for( i = 0, fr = fragments; i < numfragments; i++, fr++ ) {
		if( fr->numverts <= 0 ) {
			continue;
		}
		if( cg_numDecalVerts + (unsigned)fr->numverts > sizeof( t_verts ) / sizeof( t_verts[0] ) ) {
			return;
		}

		poly.shader = shader;
		poly.verts = &t_verts[cg_numDecalVerts];
		poly.normals = &t_norms[cg_numDecalVerts];
		poly.stcoords = &t_stcoords[cg_numDecalVerts];
		poly.colors = &t_colors[cg_numDecalVerts];
		poly.numverts = fr->numverts;
		poly.fognum = fr->fognum;
		cg_numDecalVerts += (unsigned)fr->numverts;

		for( j = 0; j < fr->numverts; j++ ) {
			vec3_t v;

			Vector4Copy( verts[fr->firstvert + j], poly.verts[j] );
			VectorCopy( axis[0], poly.normals[j] ); poly.normals[j][3] = 0;
			VectorSubtract( poly.verts[j], origin, v );
			poly.stcoords[j][0] = DotProduct( v, axis[1] ) + 0.5f;
			poly.stcoords[j][1] = DotProduct( v, axis[2] ) + 0.5f;
			*( int * )poly.colors[j] = c;
		}

		trap_R_AddPolyToScene( &poly );
	}
}
Пример #11
0
/*
* CG_AddParticles
*/
void CG_AddParticles( void ) {
	int i, j, k;
	float alpha;
	float time, time2;
	vec3_t org;
	vec3_t corner;
	byte_vec4_t color;
	int maxparticle, activeparticles;
	float alphaValues[MAX_PARTICLES];
	cparticle_t *p, *free_particles[MAX_PARTICLES];

	if( !cg_numparticles ) {
		return;
	}

	j = 0;
	maxparticle = -1;
	activeparticles = 0;

	for( i = 0, p = particles; i < cg_numparticles; i++, p++ ) {
		time = ( cg.time - p->time ) * 0.001f;
		alpha = alphaValues[i] = p->alpha + time * p->alphavel;

		if( alpha <= 0 ) { // faded out
			free_particles[j++] = p;
			continue;
		}

		maxparticle = i;
		activeparticles++;

		time2 = time * time * 0.5f;

		org[0] = p->org[0] + p->vel[0] * time + p->accel[0] * time2;
		org[1] = p->org[1] + p->vel[1] * time + p->accel[1] * time2;
		org[2] = p->org[2] + p->vel[2] * time + p->accel[2] * time2;

		color[0] = (uint8_t)( bound( 0, p->color[0], 1.0f ) * 255 );
		color[1] = (uint8_t)( bound( 0, p->color[1], 1.0f ) * 255 );
		color[2] = (uint8_t)( bound( 0, p->color[2], 1.0f ) * 255 );
		color[3] = (uint8_t)( bound( 0, alpha, 1.0f ) * 255 );

		corner[0] = org[0];
		corner[1] = org[1] - 0.5f * p->scale;
		corner[2] = org[2] - 0.5f * p->scale;

		Vector4Set( p->pVerts[0], corner[0], corner[1] + p->scale, corner[2] + p->scale, 1 );
		Vector4Set( p->pVerts[1], corner[0], corner[1], corner[2] + p->scale, 1 );
		Vector4Set( p->pVerts[2], corner[0], corner[1], corner[2], 1 );
		Vector4Set( p->pVerts[3], corner[0], corner[1] + p->scale, corner[2], 1 );
		for( k = 0; k < 4; k++ ) {
			Vector4Copy( color, p->pColor[k] );
		}

		p->poly.numverts = 4;
		p->poly.verts = p->pVerts;
		p->poly.stcoords = p->pStcoords;
		p->poly.colors = p->pColor;
		p->poly.fognum = p->fog ? 0 : -1;
		p->poly.shader = ( p->shader == NULL ) ? CG_MediaShader( cgs.media.shaderParticle ) : p->shader;

		trap_R_AddPolyToScene( &p->poly );
	}

	i = 0;
	while( maxparticle >= activeparticles ) {
		*free_particles[i++] = particles[maxparticle--];

		while( maxparticle >= activeparticles ) {
			if( alphaValues[maxparticle] <= 0 ) {
				maxparticle--;
			} else {
				break;
			}
		}
	}

	cg_numparticles = activeparticles;
}
Пример #12
0
/*
===============
CG_Tracer
===============
*/
void CG_Tracer( vec3_t source, vec3_t dest )
{
  vec3_t      forward, right;
  polyVert_t  verts[ 4 ];
  vec3_t      line;
  float       len, begin, end;
  vec3_t      start, finish;
  vec3_t      midpoint;

  // tracer
  VectorSubtract( dest, source, forward );
  len = VectorNormalize( forward );

  // start at least a little ways from the muzzle
  if( len < 100 )
    return;

  begin = 50 + random( ) * ( len - 60 );
  end = begin + cg_tracerLength.value;
  if( end > len )
    end = len;

  VectorMA( source, begin, forward, start );
  VectorMA( source, end, forward, finish );

  line[ 0 ] = DotProduct( forward, cg.refdef.viewaxis[ 1 ] );
  line[ 1 ] = DotProduct( forward, cg.refdef.viewaxis[ 2 ] );

  VectorScale( cg.refdef.viewaxis[ 1 ], line[ 1 ], right );
  VectorMA( right, -line[ 0 ], cg.refdef.viewaxis[ 2 ], right );
  VectorNormalize( right );

  VectorMA( finish, cg_tracerWidth.value, right, verts[ 0 ].xyz );
  verts[ 0 ].st[ 0 ] = 0;
  verts[ 0 ].st[ 1 ] = 1;
  verts[ 0 ].modulate[ 0 ] = 255;
  verts[ 0 ].modulate[ 1 ] = 255;
  verts[ 0 ].modulate[ 2 ] = 255;
  verts[ 0 ].modulate[ 3 ] = 255;

  VectorMA( finish, -cg_tracerWidth.value, right, verts[ 1 ].xyz );
  verts[ 1 ].st[ 0 ] = 1;
  verts[ 1 ].st[ 1 ] = 0;
  verts[ 1 ].modulate[ 0 ] = 255;
  verts[ 1 ].modulate[ 1 ] = 255;
  verts[ 1 ].modulate[ 2 ] = 255;
  verts[ 1 ].modulate[ 3 ] = 255;

  VectorMA( start, -cg_tracerWidth.value, right, 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 ] = 255;

  VectorMA( start, cg_tracerWidth.value, right, verts[ 3 ].xyz );
  verts[ 3 ].st[ 0 ] = 0;
  verts[ 3 ].st[ 1 ] = 0;
  verts[ 3 ].modulate[ 0 ] = 255;
  verts[ 3 ].modulate[ 1 ] = 255;
  verts[ 3 ].modulate[ 2 ] = 255;
  verts[ 3 ].modulate[ 3 ] = 255;

  trap_R_AddPolyToScene( cgs.media.tracerShader, 4, verts );

  midpoint[ 0 ] = ( start[ 0 ] + finish[ 0 ] ) * 0.5;
  midpoint[ 1 ] = ( start[ 1 ] + finish[ 1 ] ) * 0.5;
  midpoint[ 2 ] = ( start[ 2 ] + finish[ 2 ] ) * 0.5;

  // add the tracer sound
  trap_S_StartSound( midpoint, ENTITYNUM_WORLD, CHAN_AUTO, cgs.media.tracerSound );
}
Пример #13
0
void CG_VolumetricFog( vec3_t source, vec3_t dest ) {
	vec3_t forward, right;
	polyVert_t verts[4];
	vec3_t line;
	float len, begin, end;
	vec3_t start, finish;
	float width = 2.0;
	vec4_t rgba;

	if ( fogshader < 0 ) {
		fogshader = trap_R_RegisterShader( "nsq3_sfx/volumetricfog" );
	}

	rgba[0] = 1.0;
	rgba[1] = 1.0;
	rgba[2] = 1.0;
	rgba[3] = 1.0;

	VectorSubtract( dest, source, forward );
	len = VectorNormalize( forward );

	begin = 1;
	end = len;

	VectorMA( source, begin, forward, start );
	VectorMA( source, end, forward, finish );
	line[0] = DotProduct( forward, cg.refdef.viewaxis[1] );
	line[1] = DotProduct( forward, cg.refdef.viewaxis[2] );

	VectorScale( cg.refdef.viewaxis[1], line[1], right );
	VectorMA( right, -line[0], cg.refdef.viewaxis[2], right );
	VectorNormalize( right );

	VectorMA( finish, width, right, verts[0].xyz );
	verts[0].st[0] = 0;
	verts[0].st[1] = 1;
	verts[0].modulate[0] = 255 * rgba[0];
	verts[0].modulate[1] = 255 * rgba[1];
	verts[0].modulate[2] = 255 * rgba[2];
	verts[0].modulate[3] = 255 * rgba[3];

	VectorMA( finish, -width, right, verts[1].xyz );
	verts[1].st[0] = 1;
	verts[1].st[1] = 1;
	verts[1].modulate[0] = 255 * rgba[0];
	verts[1].modulate[1] = 255 * rgba[1];
	verts[1].modulate[2] = 255 * rgba[2];
	verts[1].modulate[3] = 255 * rgba[3];

	VectorMA( start, -width, right, verts[2].xyz );
	verts[2].st[0] = 1;
	verts[2].st[1] = 0;
	verts[2].modulate[0] = 255 * rgba[0];
	verts[2].modulate[1] = 255 * rgba[1];
	verts[2].modulate[2] = 255 * rgba[2];
	verts[2].modulate[3] = 255 * rgba[3];

	VectorMA( start, width, right, verts[3].xyz );
	verts[3].st[0] = 0;
	verts[3].st[1] = 0;
	verts[3].modulate[0] = 255 * rgba[0];
	verts[3].modulate[1] = 255 * rgba[1];
	verts[3].modulate[2] = 255 * rgba[2];
	verts[3].modulate[3] = 255 * rgba[3];

	trap_R_AddPolyToScene( fogshader, 4, verts );

}
Пример #14
0
void CG_AddParticleToScene(cparticle_t *p, vec3_t org) {

	vec3_t     point;
	polyVert_t verts[4];
	float      width;
	float      height;
	float      time, time2;
	float      ratio;
	float      invratio;
	vec3_t     color;
	polyVert_t TRIverts[3];
	vec3_t     rright2, rup2;

	if (p->type == P_WEATHER || p->type == P_WEATHER_TURBULENT || p->type == P_WEATHER_FLURRY
	    || p->type == P_BUBBLE || p->type == P_BUBBLE_TURBULENT) {   // create a front facing polygon
		if (p->type != P_WEATHER_FLURRY) {
			if (p->type == P_BUBBLE || p->type == P_BUBBLE_TURBULENT) {
				if (org[2] > p->end) {
					p->time = cg.time;
					VectorCopy(org, p->org);   // Ridah, fixes rare snow flakes that flicker on the ground

					p->org[2] = (p->start + crandom() * 4);


					if (p->type == P_BUBBLE_TURBULENT) {
						p->vel[0] = crandom() * 4;
						p->vel[1] = crandom() * 4;
					}

				}
			} else {
				if (org[2] < p->end) {
					p->time = cg.time;
					VectorCopy(org, p->org);   // Ridah, fixes rare snow flakes that flicker on the ground

					while (p->org[2] < p->end) {
						p->org[2] += (p->start - p->end);
					}


					if (p->type == P_WEATHER_TURBULENT) {
						p->vel[0] = crandom() * 16;
						p->vel[1] = crandom() * 16;
					}

				}
			}


			// Rafael snow pvs check
			if (!p->link) {
				return;
			}

			p->alpha = 1;
		}

		// Ridah, had to do this or MAX_POLYS is being exceeded in village1.bsp
		if (VectorDistanceSquared(cg.snap->ps.origin, org) > SQR(1024)) {
			return;
		}
		// done.

		if (p->type == P_BUBBLE || p->type == P_BUBBLE_TURBULENT) {
			VectorMA(org, -p->height, vup, point);
			VectorMA(point, -p->width, vright, point);
			VectorCopy(point, 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] = 255 * p->alpha;

			VectorMA(org, -p->height, vup, point);
			VectorMA(point, p->width, vright, point);
			VectorCopy(point, 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] = 255 * p->alpha;

			VectorMA(org, p->height, vup, point);
			VectorMA(point, p->width, vright, point);
			VectorCopy(point, 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] = 255 * p->alpha;

			VectorMA(org, p->height, vup, point);
			VectorMA(point, -p->width, vright, point);
			VectorCopy(point, 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] = 255 * p->alpha;
		} else {
			VectorMA(org, -p->height, vup, point);
			VectorMA(point, -p->width, vright, point);
			VectorCopy(point, TRIverts[0].xyz);
			TRIverts[0].st[0]       = 1;
			TRIverts[0].st[1]       = 0;
			TRIverts[0].modulate[0] = 255;
			TRIverts[0].modulate[1] = 255;
			TRIverts[0].modulate[2] = 255;
			TRIverts[0].modulate[3] = 255 * p->alpha;

			VectorMA(org, p->height, vup, point);
			VectorMA(point, -p->width, vright, point);
			VectorCopy(point, TRIverts[1].xyz);
			TRIverts[1].st[0]       = 0;
			TRIverts[1].st[1]       = 0;
			TRIverts[1].modulate[0] = 255;
			TRIverts[1].modulate[1] = 255;
			TRIverts[1].modulate[2] = 255;
			TRIverts[1].modulate[3] = 255 * p->alpha;

			VectorMA(org, p->height, vup, point);
			VectorMA(point, p->width, vright, point);
			VectorCopy(point, TRIverts[2].xyz);
			TRIverts[2].st[0]       = 0;
			TRIverts[2].st[1]       = 1;
			TRIverts[2].modulate[0] = 255;
			TRIverts[2].modulate[1] = 255;
			TRIverts[2].modulate[2] = 255;
			TRIverts[2].modulate[3] = 255 * p->alpha;
		}

	} else if (p->type == P_SPRITE) {
		vec3_t rr, ru;
		vec3_t rotate_ang;

		VectorSet(color, 1.0, 1.0, 1.0);
		time  = cg.time - p->time;
		time2 = p->endtime - p->time;
		ratio = time / time2;

		width  = p->width + (ratio * (p->endwidth - p->width));
		height = p->height + (ratio * (p->endheight - p->height));

		if (p->roll) {
			vectoangles(cg.refdef_current->viewaxis[0], rotate_ang);
			rotate_ang[ROLL] += p->roll;
			AngleVectors(rotate_ang, NULL, rr, ru);
		}

		if (p->roll) {
			VectorMA(org, -height, ru, point);
			VectorMA(point, -width, rr, point);
		} else {
			VectorMA(org, -height, vup, point);
			VectorMA(point, -width, vright, point);
		}
		VectorCopy(point, 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] = 255;

		if (p->roll) {
			VectorMA(point, 2 * height, ru, point);
		} else {
			VectorMA(point, 2 * height, vup, point);
		}
		VectorCopy(point, 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] = 255;

		if (p->roll) {
			VectorMA(point, 2 * width, rr, point);
		} else {
			VectorMA(point, 2 * width, vright, point);
		}
		VectorCopy(point, 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] = 255;

		if (p->roll) {
			VectorMA(point, -2 * height, ru, point);
		} else {
			VectorMA(point, -2 * height, vup, point);
		}
		VectorCopy(point, 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] = 255;
	} else if (p->type == P_SMOKE || p->type == P_SMOKE_IMPACT) {         // create a front rotating facing polygon
		if (p->type == P_SMOKE_IMPACT && VectorDistanceSquared(cg.snap->ps.origin, org) > SQR(1024)) {
			return;
		}

		if (p->color == MUSTARD) {
			VectorSet(color, 0.42, 0.33, 0.19);
		} else if (p->color == BLOODRED) {
			VectorSet(color, 0.22, 0, 0);
		} else if (p->color == ZOMBIE) {
			VectorSet(color, 0.4, 0.28, 0.23);
		} else if (p->color == GREY75) {
			float len;
			float greyit;
			float val;
			len = Distance(cg.snap->ps.origin, org);
			if (!len) {
				len = 1;
			}

			val    = 4096 / len;
			greyit = 0.25 * val;
			if (greyit > 0.5) {
				greyit = 0.5;
			}

			VectorSet(color, greyit, greyit, greyit);
		} else {
			VectorSet(color, 1.0, 1.0, 1.0);
		}

		time  = cg.time - p->time;
		time2 = p->endtime - p->time;
		ratio = time / time2;

		if (cg.time > p->startfade) {
			invratio = 1 - ((cg.time - p->startfade) / (p->endtime - p->startfade));

			if (p->color == EMISIVEFADE) {
				float fval;
				fval = (invratio * invratio);
				if (fval < 0) {
					fval = 0;
				}
				VectorSet(color, fval, fval, fval);
			}
			invratio *= p->alpha;
		} else {
			invratio = 1 * p->alpha;
		}

		if (cgs.glconfig.hardwareType == GLHW_RAGEPRO) {
			invratio = 1;
		}

		if (invratio > 1) {
			invratio = 1;
		}

		width  = p->width + (ratio * (p->endwidth - p->width));
		height = p->height + (ratio * (p->endheight - p->height));

		{
			vec3_t temp;

			vectoangles(rforward, temp);
			p->accumroll += p->roll;
			temp[ROLL]   += p->accumroll * 0.1;
			AngleVectors(temp, NULL, rright2, rup2);
		}

		if (p->rotate) {
			VectorMA(org, -height, rup2, point);
			VectorMA(point, -width, rright2, point);
		} else {
			VectorMA(org, -p->height, vup, point);
			VectorMA(point, -p->width, vright, point);
		}
		VectorCopy(point, verts[0].xyz);
		verts[0].st[0]       = 0;
		verts[0].st[1]       = 0;
		verts[0].modulate[0] = 255 * color[0];
		verts[0].modulate[1] = 255 * color[1];
		verts[0].modulate[2] = 255 * color[2];
		verts[0].modulate[3] = 255 * invratio;

		if (p->rotate) {
			VectorMA(org, -height, rup2, point);
			VectorMA(point, width, rright2, point);
		} else {
			VectorMA(org, -p->height, vup, point);
			VectorMA(point, p->width, vright, point);
		}
		VectorCopy(point, verts[1].xyz);
		verts[1].st[0]       = 0;
		verts[1].st[1]       = 1;
		verts[1].modulate[0] = 255 * color[0];
		verts[1].modulate[1] = 255 * color[1];
		verts[1].modulate[2] = 255 * color[2];
		verts[1].modulate[3] = 255 * invratio;

		if (p->rotate) {
			VectorMA(org, height, rup2, point);
			VectorMA(point, width, rright2, point);
		} else {
			VectorMA(org, p->height, vup, point);
			VectorMA(point, p->width, vright, point);
		}
		VectorCopy(point, verts[2].xyz);
		verts[2].st[0]       = 1;
		verts[2].st[1]       = 1;
		verts[2].modulate[0] = 255 * color[0];
		verts[2].modulate[1] = 255 * color[1];
		verts[2].modulate[2] = 255 * color[2];
		verts[2].modulate[3] = 255 * invratio;

		if (p->rotate) {
			VectorMA(org, height, rup2, point);
			VectorMA(point, -width, rright2, point);
		} else {
			VectorMA(org, p->height, vup, point);
			VectorMA(point, -p->width, vright, point);
		}
		VectorCopy(point, verts[3].xyz);
		verts[3].st[0]       = 1;
		verts[3].st[1]       = 0;
		verts[3].modulate[0] = 255 * color[0];
		verts[3].modulate[1] = 255 * color[1];
		verts[3].modulate[2] = 255 * color[2];
		verts[3].modulate[3] = 255  * invratio;

	} else if (p->type == P_FLAT_SCALEUP) {
		float width, height;
		float sinR, cosR;

		if (p->color == BLOODRED) {
			VectorSet(color, 1, 1, 1);
		} else {
			VectorSet(color, 0.5, 0.5, 0.5);
		}

		time  = cg.time - p->time;
		time2 = p->endtime - p->time;
		ratio = time / time2;

		width  = p->width + (ratio * (p->endwidth - p->width));
		height = p->height + (ratio * (p->endheight - p->height));

		if (width > p->endwidth) {
			width = p->endwidth;
		}

		if (height > p->endheight) {
			height = p->endheight;
		}

		sinR = height * sin(DEG2RAD(p->roll)) * ROOT_2;
		cosR = width * cos(DEG2RAD(p->roll)) * ROOT_2;

		VectorCopy(org, verts[0].xyz);
		verts[0].xyz[0]     -= sinR;
		verts[0].xyz[1]     -= cosR;
		verts[0].st[0]       = 0;
		verts[0].st[1]       = 0;
		verts[0].modulate[0] = 255 * color[0];
		verts[0].modulate[1] = 255 * color[1];
		verts[0].modulate[2] = 255 * color[2];
		verts[0].modulate[3] = 255;

		VectorCopy(org, verts[1].xyz);
		verts[1].xyz[0]     -= cosR;
		verts[1].xyz[1]     += sinR;
		verts[1].st[0]       = 0;
		verts[1].st[1]       = 1;
		verts[1].modulate[0] = verts[0].modulate[0];
		verts[1].modulate[1] = verts[0].modulate[1];
		verts[1].modulate[2] = verts[0].modulate[2];
		verts[1].modulate[3] = verts[0].modulate[3];

		VectorCopy(org, verts[2].xyz);
		verts[2].xyz[0]     += sinR;
		verts[2].xyz[1]     += cosR;
		verts[2].st[0]       = 1;
		verts[2].st[1]       = 1;
		verts[2].modulate[0] = verts[0].modulate[0];
		verts[2].modulate[1] = verts[0].modulate[1];
		verts[2].modulate[2] = verts[0].modulate[2];
		verts[2].modulate[3] = verts[0].modulate[3];

		VectorCopy(org, verts[3].xyz);
		verts[3].xyz[0]     += cosR;
		verts[3].xyz[1]     -= sinR;
		verts[3].st[0]       = 1;
		verts[3].st[1]       = 0;
		verts[3].modulate[0] = verts[0].modulate[0];
		verts[3].modulate[1] = verts[0].modulate[1];
		verts[3].modulate[2] = verts[0].modulate[2];
		verts[3].modulate[3] = verts[0].modulate[3];
	} else if (p->type == P_FLAT) {

		VectorCopy(org, verts[0].xyz);
		verts[0].xyz[0]     -= p->height;
		verts[0].xyz[1]     -= p->width;
		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] = 255;

		VectorCopy(org, verts[1].xyz);
		verts[1].xyz[0]     -= p->height;
		verts[1].xyz[1]     += p->width;
		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] = 255;

		VectorCopy(org, verts[2].xyz);
		verts[2].xyz[0]     += p->height;
		verts[2].xyz[1]     += p->width;
		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] = 255;

		VectorCopy(org, verts[3].xyz);
		verts[3].xyz[0]     += p->height;
		verts[3].xyz[1]     -= p->width;
		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] = 255;

	}
	// Ridah
	else if (p->type == P_ANIM || p->type == P_DLIGHT_ANIM) {    // ydnar
		vec3_t rr, ru;
		vec3_t rotate_ang;
		int    i, j;

		time  = cg.time - p->time;
		time2 = p->endtime - p->time;
		ratio = time / time2;
		if (ratio >= 1.0) {
			ratio = 0.9999;
		} else if (ratio < 0.0) {
			// rain - make sure that ratio isn't negative or
			// we'll walk out of bounds when j is calculated below
			ratio = 0.0001;
		}

		width  = p->width + (ratio * (p->endwidth - p->width));
		height = p->height + (ratio * (p->endheight - p->height));

		// ydnar: add dlight if necessary
		if (p->type == P_DLIGHT_ANIM) {
			// fixme: support arbitrary color
			trap_R_AddLightToScene(org, 320,    //%	1.5 * (width > height ? width : height),
			                       1.25 * (1.0 - ratio), 1.0, 0.95, 0.85, 0, 0);
		}

		// if we are "inside" this sprite, don't draw
		if (VectorDistanceSquared(cg.snap->ps.origin, org) < SQR(width / 1.5f)) {
			return;
		}

		i          = p->shaderAnim;
		j          = (int)floor(ratio * shaderAnimCounts[p->shaderAnim]);
		p->pshader = shaderAnims[i][j];

		// JPW NERVE more particle testing
		if (cg_fxflags & 1) {
			p->roll          = 0;
			p->pshader       = getTestShader();
			rotate_ang[ROLL] = 90;
		}
		// jpw

		if (p->roll) {
			vectoangles(cg.refdef_current->viewaxis[0], rotate_ang);
			rotate_ang[ROLL] += p->roll;
			AngleVectors(rotate_ang, NULL, rr, ru);
		}

		if (p->roll) {
			VectorMA(org, -height, ru, point);
			VectorMA(point, -width, rr, point);
		} else {
			VectorMA(org, -height, vup, point);
			VectorMA(point, -width, vright, point);
		}
		VectorCopy(point, 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] = 255;

		if (p->roll) {
			VectorMA(point, 2 * height, ru, point);
		} else {
			VectorMA(point, 2 * height, vup, point);
		}
		VectorCopy(point, 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] = 255;

		if (p->roll) {
			VectorMA(point, 2 * width, rr, point);
		} else {
			VectorMA(point, 2 * width, vright, point);
		}
		VectorCopy(point, 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] = 255;

		if (p->roll) {
			VectorMA(point, -2 * height, ru, point);
		} else {
			VectorMA(point, -2 * height, vup, point);
		}
		VectorCopy(point, 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] = 255;
	}
	// done.

	if (!cg_wolfparticles.integer) {
		return;
	}

	if (!p->pshader) {
		return;
	}

	if (p->type == P_WEATHER || p->type == P_WEATHER_TURBULENT || p->type == P_WEATHER_FLURRY) {
		trap_R_AddPolyToScene(p->pshader, 3, TRIverts);
	} else {
		trap_R_AddPolyToScene(p->pshader, 4, verts);
	}

}
Пример #15
0
void CGSyscall_R_AddPolysToScene( qhandle_t hShader, int numVerts, const polyVert_t *verts, int num ) { trap_R_AddPolyToScene( hShader, numVerts, verts ); }
Пример #16
0
void CG_ImpactMark( qhandle_t markShader, const vec3_t origin, const vec3_t dir, 
				   float orientation, float red, float green, float blue, float alpha,
				   qboolean alphaFade, float radius, qboolean temporary )
#endif
{
	vec3_t			axis[3];
	float			texCoordScale;
	vec3_t			originalPoints[4];
	byte			colors[4];
	int				i, j;
	int				numFragments;
	markFragment_t	markFragments[MAX_MARK_FRAGMENTS], *mf;
	vec3_t			markPoints[MAX_MARK_POINTS];
	vec3_t			projection;
#ifdef TA_WEAPSYS
	qboolean addedMark = qfalse;
#endif

	if ( !cg_addMarks.integer ) {
#ifdef TA_WEAPSYS
		return qfalse;
#else
		return;
#endif
	}

	if ( radius <= 0 ) {
		CG_Error( "CG_ImpactMark called with <= 0 radius" );
	}

#ifndef IOQ3ZTM
	//if ( markTotal >= MAX_MARK_POLYS ) {
	//	return;
	//}
#endif

	// create the texture axis
	VectorNormalize2( dir, axis[0] );
	PerpendicularVector( axis[1], axis[0] );
	RotatePointAroundVector( axis[2], axis[0], axis[1], orientation );
	CrossProduct( axis[0], axis[2], axis[1] );

	texCoordScale = 0.5 * 1.0 / radius;

	// create the full polygon
	for ( i = 0 ; i < 3 ; i++ ) {
		originalPoints[0][i] = origin[i] - radius * axis[1][i] - radius * axis[2][i];
		originalPoints[1][i] = origin[i] + radius * axis[1][i] - radius * axis[2][i];
		originalPoints[2][i] = origin[i] + radius * axis[1][i] + radius * axis[2][i];
		originalPoints[3][i] = origin[i] - radius * axis[1][i] + radius * axis[2][i];
	}

	// get the fragments
	VectorScale( dir, -20, projection );
	numFragments = trap_CM_MarkFragments( 4, (void *)originalPoints,
					projection, MAX_MARK_POINTS, markPoints[0],
					MAX_MARK_FRAGMENTS, markFragments );

	colors[0] = red * 255;
	colors[1] = green * 255;
	colors[2] = blue * 255;
	colors[3] = alpha * 255;

	for ( i = 0, mf = markFragments ; i < numFragments ; i++, mf++ ) {
		polyVert_t	*v;
		polyVert_t	verts[MAX_VERTS_ON_POLY];
		markPoly_t	*mark;
		vec3_t		delta;
		vec3_t		localOrigin;

		// create the texture axis
		VectorNormalize2( mf->projectionDir, axis[0] );
		VectorScale( axis[0], -1, axis[0] ); // ZTM: the dir was scaled to -20 before giving to renderer, turn it back around. :S
		PerpendicularVector( axis[1], axis[0] );
		RotatePointAroundVector( axis[2], axis[0], axis[1], orientation );
		CrossProduct( axis[0], axis[2], axis[1] );

		if ( mf->bmodelNum ) {
			// ZTM: TODO?: compensate for scale in the axes if necessary? see R_RotateForEntity
			// ZTM: FIXME: cgame should be able to get origin and axis from entity !
			VectorSubtract( origin, mf->bmodelOrigin, delta );
			localOrigin[0] = DotProduct( delta, mf->bmodelAxis[0] );
			localOrigin[1] = DotProduct( delta, mf->bmodelAxis[1] );
			localOrigin[2] = DotProduct( delta, mf->bmodelAxis[2] );
		} else {
			VectorCopy( origin, localOrigin );
		}

		// we have an upper limit on the complexity of polygons
		// that we store persistantly
		if ( mf->numPoints > MAX_VERTS_ON_POLY ) {
			mf->numPoints = MAX_VERTS_ON_POLY;
		}
		for ( j = 0, v = verts ; j < mf->numPoints ; j++, v++ ) {
			VectorCopy( markPoints[mf->firstPoint + j], v->xyz );

			VectorSubtract( v->xyz, localOrigin, delta );
			v->st[0] = 0.5 + DotProduct( delta, axis[1] ) * texCoordScale;
			v->st[1] = 0.5 + DotProduct( delta, axis[2] ) * texCoordScale;
			*(int *)v->modulate = *(int *)colors;
		}

		// if it is a temporary (shadow) mark, add it immediately and forget about it
		if ( temporary ) {
			trap_R_AddPolyToScene( markShader, mf->numPoints, verts, mf->bmodelNum, 0 );
			continue;
		}

		// otherwise save it persistantly
		mark = CG_AllocMark();
		mark->bmodelNum = mf->bmodelNum;
		mark->time = cg.time;
		mark->alphaFade = alphaFade;
		mark->markShader = markShader;
		mark->numVerts = mf->numPoints;
		mark->color[0] = red;
		mark->color[1] = green;
		mark->color[2] = blue;
		mark->color[3] = alpha;
		memcpy( mark->verts, verts, mf->numPoints * sizeof( verts[0] ) );
#ifndef IOQ3ZTM
		markTotal++;
#endif
#ifdef TA_WEAPSYS
		addedMark = qtrue;
#endif
	}
#ifdef TA_WEAPSYS
	return addedMark;
#endif
}
Пример #17
0
static void CG_RainParticleRender(cg_atmosphericParticle_t * particle)
{
	// Draw a raindrop

	vec3_t forward, right;
	polyVert_t verts[4];
	vec2_t line;
	float len, frac;
	vec3_t start, finish;

	if (!particle->active)
		return;

	VectorCopy(particle->pos, start);
	len = particle->height;
	if (start[2] <= particle->minz) {
		// Stop rain going through surfaces.
		len = particle->height - particle->minz + start[2];
		frac = start[2];
		VectorMA(start, len - particle->height, particle->deltaNormalized, start);

		if (!cg_lowEffects.integer) {
			frac = (ATMOSPHERIC_CUTHEIGHT - particle->minz + frac) / (float) ATMOSPHERIC_CUTHEIGHT;
			// Splash effects on different surfaces
			if (particle->contents & (CONTENTS_WATER | CONTENTS_SLIME)) {
				// Water splash
				if (cg_atmFx.effectwatershader && frac > 0 && frac < 1)
					CG_EffectMark(cg_atmFx.effectwatershader, start, particle->surfacenormal,
						      frac * 0.5, 8 - frac * 8);
			} else if (!(particle->contents & CONTENTS_LAVA)
				   && !(particle->
					surface & (SURF_NODAMAGE | SURF_NOIMPACT | SURF_NOMARKS | SURF_SKY))) {
				// Solid splash
				if (cg_atmFx.effectlandshader && frac > 0 && frac < 1)
					CG_ImpactMark(cg_atmFx.effectlandshader, start, particle->surfacenormal, 0, 1,
						      1, 1, frac * 0.5, qfalse, 3 - frac * 2, qtrue);
			}
		}
	}
	if (len <= 0)
		return;

	VectorCopy(particle->deltaNormalized, forward);
	VectorMA(start, -len, forward, finish);

	line[0] = DotProduct(forward, cg.refdef.viewaxis[1]);
	line[1] = DotProduct(forward, cg.refdef.viewaxis[2]);

	VectorScale(cg.refdef.viewaxis[1], line[1], right);
	VectorMA(right, -line[0], cg.refdef.viewaxis[2], right);
	VectorNormalize(right);

	VectorMA(finish, particle->weight, right, verts[0].xyz);
	verts[0].st[0] = 1;
	verts[0].st[1] = 0;
	verts[0].modulate[0] = 255;
	verts[0].modulate[1] = 255;
	verts[0].modulate[2] = 255;
	verts[0].modulate[3] = 0;

	VectorMA(finish, -particle->weight, right, verts[1].xyz);
	verts[1].st[0] = 0;
	verts[1].st[1] = 0;
	verts[1].modulate[0] = 255;
	verts[1].modulate[1] = 255;
	verts[1].modulate[2] = 255;
	verts[1].modulate[3] = 0;

	VectorMA(start, -particle->weight, right, verts[2].xyz);
	verts[2].st[0] = 0;
	verts[2].st[1] = 1;
	verts[2].modulate[0] = 255;
	verts[2].modulate[1] = 255;
	verts[2].modulate[2] = 255;
	verts[2].modulate[3] = 127;

	VectorMA(start, particle->weight, right, verts[3].xyz);
	verts[3].st[0] = 1;
	verts[3].st[1] = 1;
	verts[3].modulate[0] = 255;
	verts[3].modulate[1] = 255;
	verts[3].modulate[2] = 255;
	verts[3].modulate[3] = 127;

	trap_R_AddPolyToScene(*particle->effectshader, 4, verts);
}
Пример #18
0
/*
* CG_AddBlobShadow
* 
* Ok, to not use decals space we need these arrays to store the
* polygons info. We do not need the linked list nor registration
*/
static void CG_AddBlobShadow( vec3_t origin, vec3_t dir, float orient, float radius,
							 float r, float g, float b, float a, cgshadebox_t *shadeBox )
{
	int i, j, c, nverts;
	vec3_t axis[3];
	byte_vec4_t color;
	fragment_t *fr, fragments[MAX_BLOBSHADOW_FRAGMENTS];
	int numfragments;
	poly_t poly;
	vec4_t verts[MAX_BLOBSHADOW_VERTS];

	if( radius <= 0 || VectorCompare( dir, vec3_origin ) )
		return; // invalid

	// calculate orientation matrix
	VectorNormalize2( dir, axis[0] );
	PerpendicularVector( axis[1], axis[0] );
	RotatePointAroundVector( axis[2], axis[0], axis[1], orient );
	CrossProduct( axis[0], axis[2], axis[1] );

	numfragments = trap_R_GetClippedFragments( origin, radius, axis, // clip it
		MAX_BLOBSHADOW_VERTS, verts, MAX_BLOBSHADOW_FRAGMENTS, fragments );

	// no valid fragments
	if( !numfragments )
		return;

	// clamp and scale colors
	if( r < 0 ) r = 0;else if( r > 1 ) r = 255;else r *= 255;
	if( g < 0 ) g = 0;else if( g > 1 ) g = 255;else g *= 255;
	if( b < 0 ) b = 0;else if( b > 1 ) b = 255;else b *= 255;
	if( a < 0 ) a = 0;else if( a > 1 ) a = 255;else a *= 255;

	color[0] = ( qbyte )( r );
	color[1] = ( qbyte )( g );
	color[2] = ( qbyte )( b );
	color[3] = ( qbyte )( a );
	c = *( int * )color;

	radius = 0.5f / radius;
	VectorScale( axis[1], radius, axis[1] );
	VectorScale( axis[2], radius, axis[2] );

	memset( &poly, 0, sizeof( poly ) );

	for( i = 0, nverts = 0, fr = fragments; i < numfragments; i++, fr++ )
	{
		if( nverts+fr->numverts > MAX_BLOBSHADOW_VERTS )
			return;
		if( fr->numverts <= 0 )
			continue;

		poly.shader = shadeBox->shader;
		poly.verts = &shadeBox->verts[nverts];
		poly.normals = &shadeBox->norms[nverts];
		poly.stcoords = &shadeBox->stcoords[nverts];
		poly.colors = &shadeBox->colors[nverts];
		poly.numverts = fr->numverts;
		poly.fognum = fr->fognum;
		nverts += fr->numverts;

		for( j = 0; j < fr->numverts; j++ )
		{
			vec3_t v;

			Vector4Copy( verts[fr->firstvert+j], poly.verts[j] );
			VectorCopy( axis[0], poly.normals[j] ); poly.normals[j][3] = 0;
			VectorSubtract( poly.verts[j], origin, v );
			poly.stcoords[j][0] = DotProduct( v, axis[1] ) + 0.5f;
			poly.stcoords[j][1] = DotProduct( v, axis[2] ) + 0.5f;
			*( int * )poly.colors[j] = c;
		}

		trap_R_AddPolyToScene( &poly );
	}
}
void CG_AddMarks( void ) {
	int			j;
	markPoly_t	*mp, *next;
	int			t;
	int			fade;

	if ( !cg_addMarks.integer ) {
		return;
	}

	mp = cg_activeMarkPolys.nextMark;
	for ( ; mp != &cg_activeMarkPolys ; mp = next ) {
		// grab next now, so if the local entity is freed we
		// still have it
		next = mp->nextMark;

		if(mp->markShader == cgs.media.SchaumShader)
		{
			if(cg.time> mp->time + 10000 )
			{
				CG_FreeMarkPoly( mp );
				continue;
			}

			if((fade=cg.time-mp->time-8000)>=0)
			{
				fade=1.0f-(fade/2000.0f);

				if ( mp->verts[0].modulate[0] != 0 ) {
					for ( j = 0 ; j < mp->poly.numVerts ; j++ ) {
						mp->verts[j].modulate[0] = mp->color[0] * fade;
						mp->verts[j].modulate[1] = mp->color[1] * fade;
						mp->verts[j].modulate[2] = mp->color[2] * fade;
					}
				}
			}

			trap_R_AddPolyToScene( mp->markShader, mp->poly.numVerts, mp->verts );
			continue;
		}

		// see if it is time to completely remove it
		if ( cg.time > mp->time + MARK_TOTAL_TIME ) {
			CG_FreeMarkPoly( mp );
			continue;
		}

		// fade out the energy bursts
		if ( mp->markShader == cgs.media.energyMarkShader ) {

			fade = 450 - 450 * ( (cg.time - mp->time ) / 3000.0 );
			if ( fade < 255 ) {
				if ( fade < 0 ) {
					fade = 0;
				}
				if ( mp->verts[0].modulate[0] != 0 ) {
					for ( j = 0 ; j < mp->poly.numVerts ; j++ ) {
						mp->verts[j].modulate[0] = mp->color[0] * fade;
						mp->verts[j].modulate[1] = mp->color[1] * fade;
						mp->verts[j].modulate[2] = mp->color[2] * fade;
					}
				}
			}
		}

		// fade all marks out with time
		t = mp->time + MARK_TOTAL_TIME - cg.time;
		if ( t < MARK_FADE_TIME ) {
			fade = 255 * t / MARK_FADE_TIME;
			if ( mp->alphaFade ) {
				for ( j = 0 ; j < mp->poly.numVerts ; j++ ) {
					mp->verts[j].modulate[3] = fade;
				}
			} else {
				for ( j = 0 ; j < mp->poly.numVerts ; j++ ) {
					mp->verts[j].modulate[0] = mp->color[0] * fade;
					mp->verts[j].modulate[1] = mp->color[1] * fade;
					mp->verts[j].modulate[2] = mp->color[2] * fade;
				}
			}
		}


		trap_R_AddPolyToScene( mp->markShader, mp->poly.numVerts, mp->verts );
	}
}
void CG_ImpactMark( qhandle_t markShader, const vec3_t origin, const vec3_t dir, 
				   float orientation, float red, float green, float blue, float alpha,
				   qboolean alphaFade, float radius, qboolean temporary ) {
	vec3_t			axis[3];
	float			texCoordScale;
	vec3_t			originalPoints[4];
	byte			colors[4];
	int				i, j;
	int				numFragments;
	markFragment_t	markFragments[MAX_MARK_FRAGMENTS], *mf;
	vec3_t			markPoints[MAX_MARK_POINTS];
	vec3_t			projection;
	markPoly_t		*mp, *next;
	vec3_t			delta;

	if ( !cg_addMarks.integer ) {
		return;
	}

	if ( radius <= 0 ) {
		CG_Error( "CG_ImpactMark called with <= 0 radius" );
	}

	//if ( markTotal >= MAX_MARK_POLYS ) {
	//	return;
	//}

	// HERBY: Bubble G overdraw fix
	mp = cg_activeMarkPolys.nextMark;
	for ( ; mp != &cg_activeMarkPolys; mp = next ) {
		next = mp->nextMark;
		if(temporary) break; // keep all marks if the new one is just the shadow
		if(mp->markShader == cgs.media.SchaumShader) continue;//die slick-ents einfach übergehen
		VectorSubtract( mp->origin, origin, delta );
		if ( radius <= mp->radius + 4 && VectorLength( delta ) < ( radius + mp->radius ) * MIN_MARK_DISTANCE ) {
			CG_FreeMarkPoly( mp );
		}
	}	

	// create the texture axis
	VectorNormalize2( dir, axis[0] );
	PerpendicularVector( axis[1], axis[0] );
	RotatePointAroundVector( axis[2], axis[0], axis[1], orientation );
	CrossProduct( axis[0], axis[2], axis[1] );

	texCoordScale = 0.5 * 1.0 / radius;

	// create the full polygon
	for ( i = 0 ; i < 3 ; ++i ) {
		originalPoints[0][i] = origin[i] - radius * axis[1][i] - radius * axis[2][i];
		originalPoints[1][i] = origin[i] + radius * axis[1][i] - radius * axis[2][i];
		originalPoints[2][i] = origin[i] + radius * axis[1][i] + radius * axis[2][i];
		originalPoints[3][i] = origin[i] - radius * axis[1][i] + radius * axis[2][i];
	}

	// get the fragments
	VectorScale( dir, -20, projection );
	numFragments = trap_CM_MarkFragments( 4, (void *)originalPoints,
					projection, MAX_MARK_POINTS, markPoints[0],
					MAX_MARK_FRAGMENTS, markFragments );

	if(!numFragments && markShader == cgs.media.SchaumShader)
	{
		numFragments = 1;
		markFragments->firstPoint = 0;
		markFragments->numPoints = 4;
		for(i=0;i<4;++i)
			VectorCopy(originalPoints[i],markPoints[i]);
	}

	colors[0] = red * 255;
	colors[1] = green * 255;
	colors[2] = blue * 255;
	colors[3] = alpha * 255;

	for ( i = 0, mf = markFragments ; i < numFragments ; i++, mf++ ) {
		polyVert_t	*v;
		polyVert_t	verts[MAX_VERTS_ON_POLY];
		markPoly_t	*mark;

		// we have an upper limit on the complexity of polygons
		// that we store persistantly
		if ( mf->numPoints > MAX_VERTS_ON_POLY ) {
			mf->numPoints = MAX_VERTS_ON_POLY;
		}
		for ( j = 0, v = verts ; j < mf->numPoints ; j++, v++ ) {
			vec3_t		delta;

			VectorCopy( markPoints[mf->firstPoint + j], v->xyz );

			VectorSubtract( v->xyz, origin, delta );
			v->st[0] = 0.5 + DotProduct( delta, axis[1] ) * texCoordScale;
			v->st[1] = 0.5 + DotProduct( delta, axis[2] ) * texCoordScale;
			*(int *)v->modulate = *(int *)colors;
		}

		// if it is a temporary (shadow) mark, add it immediately and forget about it
		if ( temporary ) {
			trap_R_AddPolyToScene( markShader, mf->numPoints, verts );
			continue;
		}

		// otherwise save it persistantly
		mark = CG_AllocMark();
		mark->time = cg.time;
		mark->alphaFade = alphaFade;
		mark->markShader = markShader;
		mark->poly.numVerts = mf->numPoints;
		mark->color[0] = red;
		mark->color[1] = green;
		mark->color[2] = blue;
		mark->color[3] = alpha;
		mark->radius = radius;
		VectorCopy( origin, mark->origin );
		memcpy( mark->verts, verts, mf->numPoints * sizeof( verts[0] ) );
		markTotal++;
	}
}
Пример #21
0
void CG_AddMarks( void ) {
	int			j;
	markPoly_t	*mp, *next;
	int			t;
	int			fade;

	if ( !cg_addMarks.integer ) {
		return;
	}

	mp = cg_activeMarkPolys.nextMark;
	for ( ; mp != &cg_activeMarkPolys ; mp = next ) {
		// grab next now, so if the local entity is freed we
		// still have it
		next = mp->nextMark;

		// see if it is time to completely remove it
		if ( cg.time > mp->time + MARK_TOTAL_TIME ) {
			CG_FreeMarkPoly( mp );
			continue;
		}

		// fade out the energy bursts
#ifdef IOQ3ZTM // IOQ3BUGFIX: Use alphaFade instead of shader num (As only energyMark used alphaFade)
		if ( mp->alphaFade )
#else
		if ( mp->markShader == cgs.media.energyMarkShader )
#endif
		{

			fade = 450 - 450 * ( (cg.time - mp->time ) / 3000.0 );
			if ( fade < 255 ) {
				if ( fade < 0 ) {
					fade = 0;
				}
				if ( mp->verts[0].modulate[0] != 0 ) {
					for ( j = 0 ; j < mp->numVerts ; j++ ) {
						mp->verts[j].modulate[0] = mp->color[0] * fade;
						mp->verts[j].modulate[1] = mp->color[1] * fade;
						mp->verts[j].modulate[2] = mp->color[2] * fade;
					}
				}
			}
		}

		// fade all marks out with time
		t = mp->time + MARK_TOTAL_TIME - cg.time;
		if ( t < MARK_FADE_TIME ) {
			fade = 255 * t / MARK_FADE_TIME;
			if ( mp->alphaFade ) {
				for ( j = 0 ; j < mp->numVerts ; j++ ) {
					mp->verts[j].modulate[3] = fade;
				}
			} else {
				for ( j = 0 ; j < mp->numVerts ; j++ ) {
					mp->verts[j].modulate[0] = mp->color[0] * fade;
					mp->verts[j].modulate[1] = mp->color[1] * fade;
					mp->verts[j].modulate[2] = mp->color[2] * fade;
				}
			}
		}


		trap_R_AddPolyToScene( mp->markShader, mp->numVerts, mp->verts, mp->bmodelNum, 0 );
	}
}
Пример #22
0
void CG_AddMarks( void ) {
	int			j, k;
	markPoly_t	*mp, *next;
	int			t;
	int			fade;

	if ( !cg_addMarks.integer ) {
		return;
	}

	mp = cg_activeMarkPolys.nextMark;
	for ( ; mp != &cg_activeMarkPolys ; mp = next ) {
		// grab next now, so if the local entity is freed we
		// still have it
		next = mp->nextMark;

		// see if it is time to completely remove it
		if ( cg.time > mp->time + MARK_TOTAL_TIME ) {
			CG_FreeMarkPoly( mp );
			continue;
		}

		// fade out the energy bursts -- eh... don't
/*
		if ( mp->markShader == cgs.media.energyMarkShader ) {

			fade = 450 - 450 * ( (cg.time - mp->time ) / 3000.0 );
			if ( fade < 255 ) {
				if ( fade < 0 ) {
					fade = 0;
				}
				if ( mp->verts[0].modulate[0] != 0 ) {
					for ( j = 0 ; j < mp->poly.numVerts ; j++ ) {
						mp->verts[j].modulate[0] = mp->color[0] * fade;
						mp->verts[j].modulate[1] = mp->color[1] * fade;
						mp->verts[j].modulate[2] = mp->color[2] * fade;
					}
				}
			}
		}
*/

		// trippy marks :)
		if ( mp->markShader == cgs.media.energyMarkShader && cgs.valkyrMode ) {
			k = ( mp->time / 4 + cg.time / 4 ) % 256;
			for ( j = 0 ; j < mp->poly.numVerts ; j++ ) {
				mp->verts[j].modulate[0] = trippyColors[k].red;
				mp->verts[j].modulate[1] = trippyColors[k].green;
				mp->verts[j].modulate[2] = trippyColors[k].blue;
			}
		}

		// fade all marks out with time
		t = mp->time + MARK_TOTAL_TIME - cg.time;
		if ( t < MARK_FADE_TIME ) {
			fade = 255 * t / MARK_FADE_TIME;
			if ( mp->alphaFade ) {
				for ( j = 0 ; j < mp->poly.numVerts ; j++ ) {
					mp->verts[j].modulate[3] = fade;
				}
			} else {
				for ( j = 0 ; j < mp->poly.numVerts ; j++ ) {
					mp->verts[j].modulate[0] = mp->color[0] * fade;
					mp->verts[j].modulate[1] = mp->color[1] * fade;
					mp->verts[j].modulate[2] = mp->color[2] * fade;
				}
			}
		}


		trap_R_AddPolyToScene( mp->markShader, mp->poly.numVerts, mp->verts );
	}
}
Пример #23
0
void CG_ImpactMark( qhandle_t markShader, const vec3_t origin, const vec3_t dir, 
				   float orientation, float red, float green, float blue, float alpha,
				   qboolean alphaFade, float radius, qboolean temporary, int duration ) {
	vec3_t			axis[3];
	float			texCoordScale;
	vec3_t			originalPoints[4];
	byte			colors[4];
	int				i, j;
	int				numFragments;
	markFragment_t	markFragments[MAX_MARK_FRAGMENTS], *mf;
	vec5_t			markPoints[MAX_MARK_POINTS];	// Ridah, made it vec5_t so it includes S/T
	vec3_t			projection;
	int				multMaxFragments=1;

	if ( !cg_markTime.integer ) {
		return;
	}

	if ( radius <= 0 ) {
		CG_Error( "CG_ImpactMark called with <= 0 radius" );
	}

	// Ridah, if no duration, use the default
	if (duration < 0) {
		if (duration == -2) {
			multMaxFragments = -1;	// use original mapping
		}

//		duration = MARK_TOTAL_TIME;
		duration = cg_markTime.integer;
	}

	// create the texture axis
	VectorNormalize2( dir, axis[0] );
	PerpendicularVector( axis[1], axis[0] );
	RotatePointAroundVector( axis[2], axis[0], axis[1], orientation );
	CrossProduct( axis[0], axis[2], axis[1] );

	texCoordScale = 0.5 * 1.0 / radius;

	// create the full polygon
	for ( i = 0 ; i < 3 ; i++ ) {
		originalPoints[0][i] = origin[i] - radius * axis[1][i] - radius * axis[2][i];
		originalPoints[1][i] = origin[i] + radius * axis[1][i] - radius * axis[2][i];
		originalPoints[2][i] = origin[i] + radius * axis[1][i] + radius * axis[2][i];
		originalPoints[3][i] = origin[i] - radius * axis[1][i] + radius * axis[2][i];
	}

	// get the fragments
	//VectorScale( dir, -20, projection );
	VectorScale( dir, radius*2, projection );
	numFragments = trap_CM_MarkFragments( (int)orientation, (void *)originalPoints,
					projection, MAX_MARK_POINTS, (float *)&markPoints[0],
					MAX_MARK_FRAGMENTS*multMaxFragments, markFragments );

	colors[0] = red * 255;
	colors[1] = green * 255;
	colors[2] = blue * 255;
	colors[3] = alpha * 255;

	for ( i = 0, mf = markFragments ; i < numFragments ; i++, mf++ ) {
		polyVert_t	*v;
		polyVert_t	verts[MAX_VERTS_ON_POLY];
		markPoly_t	*mark;
		qboolean	hasST;

		// we have an upper limit on the complexity of polygons
		// that we store persistantly
		if ( mf->numPoints > MAX_VERTS_ON_POLY ) {
			mf->numPoints = MAX_VERTS_ON_POLY;
		}
		if (mf->numPoints < 0) {
			hasST = qtrue;
			mf->numPoints *= -1;
		} else {
			hasST = qfalse;
		}
		for ( j = 0, v = verts ; j < mf->numPoints ; j++, v++ ) {
			vec3_t		delta;

			VectorCopy( markPoints[mf->firstPoint + j], v->xyz );

			if (!hasST) {
				VectorSubtract( v->xyz, origin, delta );
				v->st[0] = 0.5 + DotProduct( delta, axis[1] ) * texCoordScale;
				v->st[1] = 0.5 + DotProduct( delta, axis[2] ) * texCoordScale;
			} else {
				v->st[0] = markPoints[mf->firstPoint + j][3];
				v->st[1] = markPoints[mf->firstPoint + j][4];
			}

			*(int *)v->modulate = *(int *)colors;
		}

		// if it is a temporary (shadow) mark, add it immediately and forget about it
		if ( temporary ) {
			trap_R_AddPolyToScene( markShader, mf->numPoints, verts );
			continue;
		}

		// otherwise save it persistantly
		mark = CG_AllocMark(cg.time + duration);
		mark->time = cg.time;
		mark->alphaFade = alphaFade;
		mark->markShader = markShader;
		mark->poly.numVerts = mf->numPoints;
		mark->color[0] = red;
		mark->color[1] = green;
		mark->color[2] = blue;
		mark->color[3] = alpha;
		mark->duration = duration;
		memcpy( mark->verts, verts, mf->numPoints * sizeof( verts[0] ) );
	}
}
Пример #24
0
static void CG_SnowParticleRender(cg_atmosphericParticle_t * particle)
{
	// Draw a snowflake

	vec3_t forward, right;
	polyVert_t verts[4];
	vec2_t line;
	float len, sinTumbling, cosTumbling, particleWidth;
	vec3_t start, finish;

	if (!particle->active)
		return;

	VectorCopy(particle->pos, start);

	sinTumbling = sin(particle->pos[2] * 0.03125f);
	cosTumbling = cos((particle->pos[2] + particle->pos[1]) * 0.03125f);

	start[0] += 24 * (1 - particle->deltaNormalized[2]) * sinTumbling;
	start[1] += 24 * (1 - particle->deltaNormalized[2]) * cosTumbling;

	len = particle->height;
	if (start[2] <= particle->minz) {
		// Stop snow going through surfaces.
		len = particle->height - particle->minz + start[2];
//		frac = start[2];
		VectorMA(start, len - particle->height, particle->deltaNormalized, start);
	}
	if (len <= 0)
		return;

	VectorCopy(particle->deltaNormalized, forward);
	VectorMA(start, -(len * sinTumbling), forward, finish);

	line[0] = DotProduct(forward, cg.refdef.viewaxis[1]);
	line[1] = DotProduct(forward, cg.refdef.viewaxis[2]);

	VectorScale(cg.refdef.viewaxis[1], line[1], right);
	VectorMA(right, -line[0], cg.refdef.viewaxis[2], right);
	VectorNormalize(right);

	particleWidth = cosTumbling * particle->weight;

	VectorMA(finish, particleWidth, right, verts[0].xyz);
	verts[0].st[0] = 1;
	verts[0].st[1] = 0;
	verts[0].modulate[0] = 255;
	verts[0].modulate[1] = 255;
	verts[0].modulate[2] = 255;
	verts[0].modulate[3] = 255;

	VectorMA(finish, -particleWidth, right, verts[1].xyz);
	verts[1].st[0] = 0;
	verts[1].st[1] = 0;
	verts[1].modulate[0] = 255;
	verts[1].modulate[1] = 255;
	verts[1].modulate[2] = 255;
	verts[1].modulate[3] = 255;

	VectorMA(start, -particleWidth, right, verts[2].xyz);
	verts[2].st[0] = 0;
	verts[2].st[1] = 1;
	verts[2].modulate[0] = 255;
	verts[2].modulate[1] = 255;
	verts[2].modulate[2] = 255;
	verts[2].modulate[3] = 255;

	VectorMA(start, particleWidth, right, verts[3].xyz);
	verts[3].st[0] = 1;
	verts[3].st[1] = 1;
	verts[3].modulate[0] = 255;
	verts[3].modulate[1] = 255;
	verts[3].modulate[2] = 255;
	verts[3].modulate[3] = 255;

	trap_R_AddPolyToScene(*particle->effectshader, 4, verts);
}
Пример #25
0
void CG_ImpactMark( qhandle_t markShader, const vec3_t origin, const vec3_t dir,
                    float orientation, float red, float green, float blue, float alpha,
                    bool alphaFade, float radius, bool temporary )
{
	vec3_t         axis[ 3 ];
	float          texCoordScale;
	vec3_t         originalPoints[ 4 ];
	byte           colors[ 4 ];
	int            i, j;
	int            numFragments;
	markFragment_t markFragments[ MAX_MARK_FRAGMENTS ], *mf;
	vec3_t         markPoints[ MAX_MARK_POINTS ];
	vec3_t         projection;

	if ( !cg_addMarks.integer )
	{
		return;
	}

	if( temporary )
	{
		if( CG_CullPointAndRadius( origin, M_SQRT2 * radius ) )
		{
			return;
		}
	}

	if ( radius <= 0 )
	{
		Com_Error(errorParm_t::ERR_DROP,  "CG_ImpactMark called with <= 0 radius" );
	}

	//if ( markTotal >= MAX_MARK_POLYS ) {
	//  return;
	//}

	// create the texture axis
	VectorNormalize2( dir, axis[ 0 ] );
	PerpendicularVector( axis[ 1 ], axis[ 0 ] );
	RotatePointAroundVector( axis[ 2 ], axis[ 0 ], axis[ 1 ], orientation );
	CrossProduct( axis[ 0 ], axis[ 2 ], axis[ 1 ] );

	texCoordScale = 0.5 * 1.0 / radius;

	// create the full polygon
	for ( i = 0; i < 3; i++ )
	{
		originalPoints[ 0 ][ i ] = origin[ i ] - radius * axis[ 1 ][ i ] - radius * axis[ 2 ][ i ];
		originalPoints[ 1 ][ i ] = origin[ i ] + radius * axis[ 1 ][ i ] - radius * axis[ 2 ][ i ];
		originalPoints[ 2 ][ i ] = origin[ i ] + radius * axis[ 1 ][ i ] + radius * axis[ 2 ][ i ];
		originalPoints[ 3 ][ i ] = origin[ i ] - radius * axis[ 1 ][ i ] + radius * axis[ 2 ][ i ];
	}

	// get the fragments
	VectorScale( dir, -20, projection );
	numFragments = trap_CM_MarkFragments( 4, ( const vec3_t * ) originalPoints,
	                                      projection, MAX_MARK_POINTS, markPoints[ 0 ],
	                                      MAX_MARK_FRAGMENTS, markFragments );

	colors[ 0 ] = red * 255;
	colors[ 1 ] = green * 255;
	colors[ 2 ] = blue * 255;
	colors[ 3 ] = alpha * 255;

	for ( i = 0, mf = markFragments; i < numFragments; i++, mf++ )
	{
		polyVert_t *v;
		polyVert_t verts[ MAX_VERTS_ON_POLY ];
		markPoly_t *mark;

		// we have an upper limit on the complexity of polygons
		// that we store persistently
		if ( mf->numPoints > MAX_VERTS_ON_POLY )
		{
			mf->numPoints = MAX_VERTS_ON_POLY;
		}

		for ( j = 0, v = verts; j < mf->numPoints; j++, v++ )
		{
			vec3_t delta;

			VectorCopy( markPoints[ mf->firstPoint + j ], v->xyz );

			VectorSubtract( v->xyz, origin, delta );
			v->st[ 0 ] = 0.5 + DotProduct( delta, axis[ 1 ] ) * texCoordScale;
			v->st[ 1 ] = 0.5 + DotProduct( delta, axis[ 2 ] ) * texCoordScale;
			* ( int * ) v->modulate = * ( int * ) colors;
		}

		// if it is a temporary (shadow) mark, add it immediately and forget about it
		if ( temporary )
		{
			trap_R_AddPolyToScene( markShader, mf->numPoints, verts );
			continue;
		}

		// otherwise save it persistently
		mark = CG_AllocMark();
		mark->time = cg.time;
		mark->alphaFade = alphaFade;
		mark->markShader = markShader;
		mark->poly.numVerts = mf->numPoints;
		mark->color[ 0 ] = red;
		mark->color[ 1 ] = green;
		mark->color[ 2 ] = blue;
		mark->color[ 3 ] = alpha;
		memcpy( mark->verts, verts, mf->numPoints * sizeof( verts[ 0 ] ) );
		markTotal++;
	}
}
Пример #26
0
/*
=====================
CG_AddParticleToScene
=====================
*/
void CG_AddParticleToScene (cparticle_t *p, vec3_t org, float alpha)
{

	vec3_t		point;
	polyVert_t	verts[4];
	float		width;
	float		height;
	float		time, time2;
	float		ratio;
	float		invratio;
	vec3_t		color;
	polyVert_t	TRIverts[3];
	vec3_t		rright2, rup2;

	if (p->type == P_WEATHER || p->type == P_WEATHER_TURBULENT || p->type == P_WEATHER_FLURRY
		|| p->type == P_BUBBLE || p->type == P_BUBBLE_TURBULENT)
	{// create a front facing polygon
			
		if (p->type != P_WEATHER_FLURRY)
		{
			if (p->type == P_BUBBLE || p->type == P_BUBBLE_TURBULENT)
			{
				if (org[2] > p->end)			
				{	
					p->time = cg.time;	
					VectorCopy (org, p->org); // Ridah, fixes rare snow flakes that flicker on the ground
									
					p->org[2] = ( p->start + crandom () * 4 );
					
					
					if (p->type == P_BUBBLE_TURBULENT)
					{
						p->vel[0] = crandom() * 4;
						p->vel[1] = crandom() * 4;
					}
				
				}
			}
			else
			{
				if (org[2] < p->end)			
				{	
					p->time = cg.time;	
					VectorCopy (org, p->org); // Ridah, fixes rare snow flakes that flicker on the ground
									
					while (p->org[2] < p->end) 
					{
						p->org[2] += (p->start - p->end); 
					}
					
					
					if (p->type == P_WEATHER_TURBULENT)
					{
						p->vel[0] = crandom() * 16;
						p->vel[1] = crandom() * 16;
					}
				
				}
			}
			

			// Rafael snow pvs check
			if (!p->link)
				return;

			p->alpha = 1;
		}
		
		// Ridah, had to do this or MAX_POLYS is being exceeded in village1.bsp
		if (Distance( cg.snap->ps.origin, org ) > 1024) {
			return;
		}
		// done.
	
		if (p->type == P_BUBBLE || p->type == P_BUBBLE_TURBULENT)
		{
			VectorMA (org, -p->height, pvup, point);	
			VectorMA (point, -p->width, pvright, point);	
			VectorCopy (point, 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] = 255 * p->alpha;	

			VectorMA (org, -p->height, pvup, point);	
			VectorMA (point, p->width, pvright, point);	
			VectorCopy (point, 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] = 255 * p->alpha;	

			VectorMA (org, p->height, pvup, point);	
			VectorMA (point, p->width, pvright, point);	
			VectorCopy (point, 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] = 255 * p->alpha;	

			VectorMA (org, p->height, pvup, point);	
			VectorMA (point, -p->width, pvright, point);	
			VectorCopy (point, 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] = 255 * p->alpha;	
		}
		else
		{
			VectorMA (org, -p->height, pvup, point);	
			VectorMA (point, -p->width, pvright, point);	
			VectorCopy( point, TRIverts[0].xyz );
			TRIverts[0].st[0] = 1;
			TRIverts[0].st[1] = 0;
			TRIverts[0].modulate[0] = 255;
			TRIverts[0].modulate[1] = 255;
			TRIverts[0].modulate[2] = 255;
			TRIverts[0].modulate[3] = 255 * p->alpha;	

			VectorMA (org, p->height, pvup, point);	
			VectorMA (point, -p->width, pvright, point);	
			VectorCopy (point, TRIverts[1].xyz);	
			TRIverts[1].st[0] = 0;
			TRIverts[1].st[1] = 0;
			TRIverts[1].modulate[0] = 255;
			TRIverts[1].modulate[1] = 255;
			TRIverts[1].modulate[2] = 255;
			TRIverts[1].modulate[3] = 255 * p->alpha;	

			VectorMA (org, p->height, pvup, point);	
			VectorMA (point, p->width, pvright, point);	
			VectorCopy (point, TRIverts[2].xyz);	
			TRIverts[2].st[0] = 0;
			TRIverts[2].st[1] = 1;
			TRIverts[2].modulate[0] = 255;
			TRIverts[2].modulate[1] = 255;
			TRIverts[2].modulate[2] = 255;
			TRIverts[2].modulate[3] = 255 * p->alpha;	
		}
	
	}
	else if (p->type == P_SPRITE)
	{
		vec3_t	rr, ru;
		vec3_t	rotate_ang;

		VectorSet (color, 1.0, 1.0, 0.5);
		time = cg.time - p->time;
		time2 = p->endtime - p->time;
		ratio = time / time2;

		width = p->width + ( ratio * ( p->endwidth - p->width) );
		height = p->height + ( ratio * ( p->endheight - p->height) );

		if (p->roll) {
			vectoangles( cg.refdef.viewaxis[0], rotate_ang );
			rotate_ang[ROLL] += p->roll;
			AngleVectors ( rotate_ang, NULL, rr, ru);
		}

		if (p->roll) {
			VectorMA (org, -height, ru, point);	
			VectorMA (point, -width, rr, point);	
		} else {
			VectorMA (org, -height, pvup, point);	
			VectorMA (point, -width, pvright, point);	
		}
		VectorCopy (point, 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] = 255;

		if (p->roll) {
			VectorMA (point, 2*height, ru, point);	
		} else {
			VectorMA (point, 2*height, pvup, point);	
		}
		VectorCopy (point, 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] = 255;	

		if (p->roll) {
			VectorMA (point, 2*width, rr, point);	
		} else {
			VectorMA (point, 2*width, pvright, point);	
		}
		VectorCopy (point, 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] = 255;	

		if (p->roll) {
			VectorMA (point, -2*height, ru, point);	
		} else {
			VectorMA (point, -2*height, pvup, point);	
		}
		VectorCopy (point, 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] = 255;	
	}
	else if (p->type == P_SMOKE || p->type == P_SMOKE_IMPACT)
	{// create a front rotating facing polygon

		if ( p->type == P_SMOKE_IMPACT && Distance( cg.snap->ps.origin, org ) > 1024) {
			return;
		}

		if (p->color == BLOODRED)
			VectorSet (color, 0.22f, 0.0f, 0.0f);
		else if (p->color == GREY75)
		{
			float	len;
			float	greyit;
			float	val;
			len = Distance (cg.snap->ps.origin, org);
			if (!len)
				len = 1;

			val = 4096/len;
			greyit = 0.25 * val;
			if (greyit > 0.5)
				greyit = 0.5;

			VectorSet (color, greyit, greyit, greyit);
		}
		else
			VectorSet (color, 1.0, 1.0, 1.0);

		time = cg.time - p->time;
		time2 = p->endtime - p->time;
		ratio = time / time2;
		
		if (cg.time > p->startfade)
		{
			invratio = 1 - ( (cg.time - p->startfade) / (p->endtime - p->startfade) );

			if (p->color == EMISIVEFADE)
			{
				float fval;
				fval = (invratio * invratio);
				if (fval < 0)
					fval = 0;
				VectorSet (color, fval , fval , fval );
			}
			invratio *= p->alpha;
		}
		else 
			invratio = 1 * p->alpha;

		if ( cgs.glconfig.hardwareType == GLHW_RAGEPRO )
			invratio = 1;

		if (invratio > 1)
			invratio = 1;
	
		width = p->width + ( ratio * ( p->endwidth - p->width) );
		height = p->height + ( ratio * ( p->endheight - p->height) );

		if (p->type != P_SMOKE_IMPACT)
		{
			vec3_t temp;

			vectoangles (rforward, temp);
			p->accumroll += p->roll;
			temp[ROLL] += p->accumroll * 0.1;
			AngleVectors ( temp, NULL, rright2, rup2);
		}
		else
		{
			VectorCopy (rright, rright2);
			VectorCopy (rup, rup2);
		}
		
		if (p->rotate)
		{
			VectorMA (org, -height, rup2, point);	
			VectorMA (point, -width, rright2, point);	
		}
		else
		{
			VectorMA (org, -p->height, pvup, point);	
			VectorMA (point, -p->width, pvright, point);	
		}
		VectorCopy (point, verts[0].xyz);	
		verts[0].st[0] = 0;	
		verts[0].st[1] = 0;	
		verts[0].modulate[0] = 255 * color[0];	
		verts[0].modulate[1] = 255 * color[1];	
		verts[0].modulate[2] = 255 * color[2];	
		verts[0].modulate[3] = 255 * invratio;	

		if (p->rotate)
		{
			VectorMA (org, -height, rup2, point);	
			VectorMA (point, width, rright2, point);	
		}
		else
		{
			VectorMA (org, -p->height, pvup, point);	
			VectorMA (point, p->width, pvright, point);	
		}
		VectorCopy (point, verts[1].xyz);	
		verts[1].st[0] = 0;	
		verts[1].st[1] = 1;	
		verts[1].modulate[0] = 255 * color[0];	
		verts[1].modulate[1] = 255 * color[1];	
		verts[1].modulate[2] = 255 * color[2];	
		verts[1].modulate[3] = 255 * invratio;	

		if (p->rotate)
		{
			VectorMA (org, height, rup2, point);	
			VectorMA (point, width, rright2, point);	
		}
		else
		{
			VectorMA (org, p->height, pvup, point);	
			VectorMA (point, p->width, pvright, point);	
		}
		VectorCopy (point, verts[2].xyz);	
		verts[2].st[0] = 1;	
		verts[2].st[1] = 1;	
		verts[2].modulate[0] = 255 * color[0];	
		verts[2].modulate[1] = 255 * color[1];	
		verts[2].modulate[2] = 255 * color[2];	
		verts[2].modulate[3] = 255 * invratio;	

		if (p->rotate)
		{
			VectorMA (org, height, rup2, point);	
			VectorMA (point, -width, rright2, point);	
		}
		else
		{
			VectorMA (org, p->height, pvup, point);	
			VectorMA (point, -p->width, pvright, point);	
		}
		VectorCopy (point, verts[3].xyz);	
		verts[3].st[0] = 1;	
		verts[3].st[1] = 0;	
		verts[3].modulate[0] = 255 * color[0];	
		verts[3].modulate[1] = 255 * color[1];	
		verts[3].modulate[2] = 255 * color[2];	
		verts[3].modulate[3] = 255  * invratio;	
		
	}
	else if (p->type == P_BLEED)
	{
		vec3_t	rr, ru;
		vec3_t	rotate_ang;
		float	alpha;

		alpha = p->alpha;
		
		if ( cgs.glconfig.hardwareType == GLHW_RAGEPRO )
			alpha = 1;

		if (p->roll) 
		{
			vectoangles( cg.refdef.viewaxis[0], rotate_ang );
			rotate_ang[ROLL] += p->roll;
			AngleVectors ( rotate_ang, NULL, rr, ru);
		}
		else
		{
			VectorCopy (pvup, ru);
			VectorCopy (pvright, rr);
		}

		VectorMA (org, -p->height, ru, point);	
		VectorMA (point, -p->width, rr, point);	
		VectorCopy (point, verts[0].xyz);	
		verts[0].st[0] = 0;	
		verts[0].st[1] = 0;	
		verts[0].modulate[0] = 111;	
		verts[0].modulate[1] = 19;	
		verts[0].modulate[2] = 9;	
		verts[0].modulate[3] = 255 * alpha;	

		VectorMA (org, -p->height, ru, point);	
		VectorMA (point, p->width, rr, point);	
		VectorCopy (point, verts[1].xyz);	
		verts[1].st[0] = 0;	
		verts[1].st[1] = 1;	
		verts[1].modulate[0] = 111;	
		verts[1].modulate[1] = 19;	
		verts[1].modulate[2] = 9;	
		verts[1].modulate[3] = 255 * alpha;	

		VectorMA (org, p->height, ru, point);	
		VectorMA (point, p->width, rr, point);	
		VectorCopy (point, verts[2].xyz);	
		verts[2].st[0] = 1;	
		verts[2].st[1] = 1;	
		verts[2].modulate[0] = 111;	
		verts[2].modulate[1] = 19;	
		verts[2].modulate[2] = 9;	
		verts[2].modulate[3] = 255 * alpha;	

		VectorMA (org, p->height, ru, point);	
		VectorMA (point, -p->width, rr, point);	
		VectorCopy (point, verts[3].xyz);	
		verts[3].st[0] = 1;	
		verts[3].st[1] = 0;	
		verts[3].modulate[0] = 111;	
		verts[3].modulate[1] = 19;	
		verts[3].modulate[2] = 9;	
		verts[3].modulate[3] = 255 * alpha;	

	}
	else if (p->type == P_FLAT_SCALEUP)
	{
		float width, height;
		float sinR, cosR;

		if (p->color == BLOODRED)
			VectorSet (color, 1, 1, 1);
		else
			VectorSet (color, 0.5, 0.5, 0.5);
		
		time = cg.time - p->time;
		time2 = p->endtime - p->time;
		ratio = time / time2;

		width = p->width + ( ratio * ( p->endwidth - p->width) );
		height = p->height + ( ratio * ( p->endheight - p->height) );

		if (width > p->endwidth)
			width = p->endwidth;

		if (height > p->endheight)
			height = p->endheight;

		sinR = height * sin(DEG2RAD(p->roll)) * sqrt(2);
		cosR = width * cos(DEG2RAD(p->roll)) * sqrt(2);

		VectorCopy (org, verts[0].xyz);	
		verts[0].xyz[0] -= sinR;
		verts[0].xyz[1] -= cosR;
		verts[0].st[0] = 0;	
		verts[0].st[1] = 0;	
		verts[0].modulate[0] = 255 * color[0];	
		verts[0].modulate[1] = 255 * color[1];	
		verts[0].modulate[2] = 255 * color[2];	
		verts[0].modulate[3] = 255;	

		VectorCopy (org, verts[1].xyz);	
		verts[1].xyz[0] -= cosR;	
		verts[1].xyz[1] += sinR;	
		verts[1].st[0] = 0;	
		verts[1].st[1] = 1;	
		verts[1].modulate[0] = 255 * color[0];	
		verts[1].modulate[1] = 255 * color[1];	
		verts[1].modulate[2] = 255 * color[2];	
		verts[1].modulate[3] = 255;	

		VectorCopy (org, verts[2].xyz);	
		verts[2].xyz[0] += sinR;	
		verts[2].xyz[1] += cosR;	
		verts[2].st[0] = 1;	
		verts[2].st[1] = 1;	
		verts[2].modulate[0] = 255 * color[0];	
		verts[2].modulate[1] = 255 * color[1];	
		verts[2].modulate[2] = 255 * color[2];	
		verts[2].modulate[3] = 255;	

		VectorCopy (org, verts[3].xyz);	
		verts[3].xyz[0] += cosR;	
		verts[3].xyz[1] -= sinR;	
		verts[3].st[0] = 1;	
		verts[3].st[1] = 0;	
		verts[3].modulate[0] = 255 * color[0];	
		verts[3].modulate[1] = 255 * color[1];	
		verts[3].modulate[2] = 255 * color[2];	
		verts[3].modulate[3] = 255;		
	}
	else if (p->type == P_FLAT)
	{

		VectorCopy (org, verts[0].xyz);	
		verts[0].xyz[0] -= p->height;	
		verts[0].xyz[1] -= p->width;	
		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] = 255;	

		VectorCopy (org, verts[1].xyz);	
		verts[1].xyz[0] -= p->height;	
		verts[1].xyz[1] += p->width;	
		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] = 255;	

		VectorCopy (org, verts[2].xyz);	
		verts[2].xyz[0] += p->height;	
		verts[2].xyz[1] += p->width;	
		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] = 255;	

		VectorCopy (org, verts[3].xyz);	
		verts[3].xyz[0] += p->height;	
		verts[3].xyz[1] -= p->width;	
		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] = 255;	

	}
	// Ridah
	else if (p->type == P_ANIM) {
		vec3_t	rr, ru;
		vec3_t	rotate_ang;
		int i, j;

		time = cg.time - p->time;
		time2 = p->endtime - p->time;
		ratio = time / time2;
		if (ratio >= 1.0f) {
			ratio = 0.9999f;
		}

		width = p->width + ( ratio * ( p->endwidth - p->width) );
		height = p->height + ( ratio * ( p->endheight - p->height) );

		// if we are "inside" this sprite, don't draw
		if (Distance( cg.snap->ps.origin, org ) < width/1.5) {
			return;
		}

		i = p->shaderAnim;
		j = (int)floor(ratio * shaderAnimCounts[p->shaderAnim]);
		p->pshader = shaderAnims[i][j];

		if (p->roll) {
			vectoangles( cg.refdef.viewaxis[0], rotate_ang );
			rotate_ang[ROLL] += p->roll;
			AngleVectors ( rotate_ang, NULL, rr, ru);
		}

		if (p->roll) {
			VectorMA (org, -height, ru, point);	
			VectorMA (point, -width, rr, point);	
		} else {
			VectorMA (org, -height, pvup, point);	
			VectorMA (point, -width, pvright, point);	
		}
		VectorCopy (point, 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] = 255;

		if (p->roll) {
			VectorMA (point, 2*height, ru, point);	
		} else {
			VectorMA (point, 2*height, pvup, point);	
		}
		VectorCopy (point, 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] = 255;	

		if (p->roll) {
			VectorMA (point, 2*width, rr, point);	
		} else {
			VectorMA (point, 2*width, pvright, point);	
		}
		VectorCopy (point, 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] = 255;	

		if (p->roll) {
			VectorMA (point, -2*height, ru, point);	
		} else {
			VectorMA (point, -2*height, pvup, point);	
		}
		VectorCopy (point, 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] = 255;	
	}
	// done.
	
	if (!p->pshader) {
// (SA) temp commented out for DM
//		CG_Printf ("CG_AddParticleToScene type %d p->pshader == ZERO\n", p->type);
		return;
	}

	if (p->type == P_WEATHER || p->type == P_WEATHER_TURBULENT || p->type == P_WEATHER_FLURRY)
		trap_R_AddPolyToScene( p->pshader, 3, TRIverts );
	else
		trap_R_AddPolyToScene( p->pshader, 4, verts );

}
Пример #27
0
/*
================
CG_DrawBinaryShadersFinalPhases
================
*/
static void CG_DrawBinaryShadersFinalPhases()
{
	float      ss;
	char       str[ 20 ];
	float      f, l, u;
	polyVert_t verts[ 4 ] =
	{
		{ { 0, 0, 0 }, { 0, 0 }, { 255, 255, 255, 255 } },
		{ { 0, 0, 0 }, { 1, 0 }, { 255, 255, 255, 255 } },
		{ { 0, 0, 0 }, { 1, 1 }, { 255, 255, 255, 255 } },
		{ { 0, 0, 0 }, { 0, 1 }, { 255, 255, 255, 255 } }
	};

	if ( !cg.numBinaryShadersUsed )
	{
		return;
	}

	ss = cg_binaryShaderScreenScale.value;

	if ( ss <= 0.0f )
	{
		cg.numBinaryShadersUsed = 0;
		return;
	}
	else if ( ss > 1.0f )
	{
		ss = 1.0f;
	}

	ss = sqrt( ss );

	trap_Cvar_VariableStringBuffer( "r_znear", str, sizeof( str ) );
	f = atof( str ) + 0.01;
	l = f * tan( DEG2RAD( cg.refdef.fov_x / 2 ) ) * ss;
	u = f * tan( DEG2RAD( cg.refdef.fov_y / 2 ) ) * ss;

	VectorMA( cg.refdef.vieworg, f, cg.refdef.viewaxis[ 0 ], verts[ 0 ].xyz );
	VectorMA( verts[ 0 ].xyz, l, cg.refdef.viewaxis[ 1 ], verts[ 0 ].xyz );
	VectorMA( verts[ 0 ].xyz, u, cg.refdef.viewaxis[ 2 ], verts[ 0 ].xyz );
	VectorMA( verts[ 0 ].xyz, -2 * l, cg.refdef.viewaxis[ 1 ], verts[ 1 ].xyz );
	VectorMA( verts[ 1 ].xyz, -2 * u, cg.refdef.viewaxis[ 2 ], verts[ 2 ].xyz );
	VectorMA( verts[ 0 ].xyz, -2 * u, cg.refdef.viewaxis[ 2 ], verts[ 3 ].xyz );

	trap_R_AddPolyToScene( cgs.media.binaryAlpha1Shader, 4, verts );

	for ( int i = 0; i < cg.numBinaryShadersUsed; ++i )
	{
		for ( int j = 0; j < 4; ++j )
		{
			auto alpha = verts[ j ].modulate[ 3 ];
			cg.binaryShaderSettings[ i ].color.ToArray( verts[ j ].modulate );
			verts[ j ].modulate[ 3 ] = alpha;
		}

		if ( cg.binaryShaderSettings[ i ].drawFrontline )
		{
			trap_R_AddPolyToScene( cgs.media.binaryShaders[ i ].f3, 4, verts );
		}

		if ( cg.binaryShaderSettings[ i ].drawIntersection )
		{
			trap_R_AddPolyToScene( cgs.media.binaryShaders[ i ].b3, 4, verts );
		}
	}

	cg.numBinaryShadersUsed = 0;
}
Пример #28
0
/**
 * @brief CG_AddParticleToScene
 * @param[in,out] p
 * @param[in] org
 * @param alpha - unused
 */
void CG_AddParticleToScene(cparticle_t *p, vec3_t org, float alpha)
{
	polyVert_t verts[4];
	polyVert_t TRIverts[3];

	switch (p->type)
	{
	case P_WEATHER:
	case P_WEATHER_TURBULENT:
	case P_WEATHER_FLURRY:
	case P_BUBBLE:
	case P_BUBBLE_TURBULENT:  // create a front facing polygon
	{
		if (p->type != P_WEATHER_FLURRY)
		{
			if (p->type == P_BUBBLE || p->type == P_BUBBLE_TURBULENT)
			{
				if (org[2] > p->end)
				{
					p->time = cg.time;
					VectorCopy(org, p->org);   // fixes rare snow flakes that flicker on the ground

					p->org[2] = (p->start + crandom() * 4);

					if (p->type == P_BUBBLE_TURBULENT)
					{
						p->vel[0] = crandom() * 4;
						p->vel[1] = crandom() * 4;
					}
				}
			}
			else
			{
				if (org[2] < p->end)
				{
					p->time = cg.time;
					VectorCopy(org, p->org);   // fixes rare snow flakes that flicker on the ground

					while (p->org[2] < p->end)
					{
						p->org[2] += (p->start - p->end);
					}

					if (p->type == P_WEATHER_TURBULENT)
					{
						p->vel[0] = crandom() * 16;
						p->vel[1] = crandom() * 16;
					}
				}
			}

			// snow pvs check
			if (!p->link)
			{
				return;
			}

			p->alpha = 1;
		}

		// had to do this or MAX_POLYS is being exceeded in village1.bsp
		if (VectorDistanceSquared(cg.snap->ps.origin, org) > Square(1024))
		{
			return;
		}

		if (p->type == P_BUBBLE || p->type == P_BUBBLE_TURBULENT)
		{
			vec3_t point;

			VectorMA(org, -p->height, vup, point);
			VectorMA(point, -p->width, vright, point);
			VectorCopy(point, 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] = (byte)(255 * p->alpha);

			VectorMA(org, -p->height, vup, point);
			VectorMA(point, p->width, vright, point);
			VectorCopy(point, 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] = (byte)(255 * p->alpha);

			VectorMA(org, p->height, vup, point);
			VectorMA(point, p->width, vright, point);
			VectorCopy(point, 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] = (byte)(255 * p->alpha);

			VectorMA(org, p->height, vup, point);
			VectorMA(point, -p->width, vright, point);
			VectorCopy(point, 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] = (byte)(255 * p->alpha);
		}
		else
		{
			vec3_t point;

			VectorMA(org, -p->height, vup, point);
			VectorMA(point, -p->width, vright, point);
			VectorCopy(point, TRIverts[0].xyz);
			TRIverts[0].st[0]       = 1;
			TRIverts[0].st[1]       = 0;
			TRIverts[0].modulate[0] = 255;
			TRIverts[0].modulate[1] = 255;
			TRIverts[0].modulate[2] = 255;
			TRIverts[0].modulate[3] = (byte)(255 * p->alpha);

			VectorMA(org, p->height, vup, point);
			VectorMA(point, -p->width, vright, point);
			VectorCopy(point, TRIverts[1].xyz);
			TRIverts[1].st[0]       = 0;
			TRIverts[1].st[1]       = 0;
			TRIverts[1].modulate[0] = 255;
			TRIverts[1].modulate[1] = 255;
			TRIverts[1].modulate[2] = 255;
			TRIverts[1].modulate[3] = (byte)(255 * p->alpha);

			VectorMA(org, p->height, vup, point);
			VectorMA(point, p->width, vright, point);
			VectorCopy(point, TRIverts[2].xyz);
			TRIverts[2].st[0]       = 0;
			TRIverts[2].st[1]       = 1;
			TRIverts[2].modulate[0] = 255;
			TRIverts[2].modulate[1] = 255;
			TRIverts[2].modulate[2] = 255;
			TRIverts[2].modulate[3] = (byte)(255 * p->alpha);
		}
	}
	break;
	case P_SPRITE:
	{
		vec3_t point, rr, ru, rotate_ang;
		float  time   = cg.time - p->time;
		float  time2  = p->endtime - p->time;
		float  ratio  = time / time2;
		float  width  = p->width + (ratio * (p->endwidth - p->width));
		float  height = p->height + (ratio * (p->endheight - p->height));

		if (p->roll)
		{
			vectoangles(cg.refdef_current->viewaxis[0], rotate_ang);
			rotate_ang[ROLL] += p->roll;
			AngleVectors(rotate_ang, NULL, rr, ru);
		}

		if (p->roll)
		{
			VectorMA(org, -height, ru, point);
			VectorMA(point, -width, rr, point);
		}
		else
		{
			VectorMA(org, -height, vup, point);
			VectorMA(point, -width, vright, point);
		}
		VectorCopy(point, 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] = 255;

		if (p->roll)
		{
			VectorMA(point, 2 * height, ru, point);
		}
		else
		{
			VectorMA(point, 2 * height, vup, point);
		}
		VectorCopy(point, 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] = 255;

		if (p->roll)
		{
			VectorMA(point, 2 * width, rr, point);
		}
		else
		{
			VectorMA(point, 2 * width, vright, point);
		}
		VectorCopy(point, 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] = 255;

		if (p->roll)
		{
			VectorMA(point, -2 * height, ru, point);
		}
		else
		{
			VectorMA(point, -2 * height, vup, point);
		}
		VectorCopy(point, 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] = 255;
	}
	break;
	case P_SMOKE:
	case P_SMOKE_IMPACT: // create a front rotating facing polygon
	{
		vec3_t point, rup2, rright2, color;
		float  invratio, time, time2, ratio, width, height;

		if (p->type == P_SMOKE_IMPACT && VectorDistanceSquared(cg.snap->ps.origin, org) > Square(1024))
		{
			return;
		}

		if (p->color == MUSTARD)
		{
			VectorSet(color, 0.42f, 0.33f, 0.19f);
		}
		else if (p->color == BLOODRED)
		{
			VectorSet(color, 0.22f, 0, 0);
		}
		else if (p->color == ZOMBIE)
		{
			VectorSet(color, 0.4f, 0.28f, 0.23f);
		}
		else if (p->color == GREY75)
		{
			float len, greyit;

			len = Distance(cg.snap->ps.origin, org);
			if (len == 0.f)
			{
				len = 1;
			}

			//val    = 4096 / len;
			greyit = 0.25f * (4096 / len);
			if (greyit > 0.5f)
			{
				greyit = 0.5f;
			}

			VectorSet(color, greyit, greyit, greyit);
		}
		else
		{
			VectorSet(color, 1.0f, 1.0f, 1.0f);
		}

		time  = cg.time - p->time;
		time2 = p->endtime - p->time;
		ratio = time / time2;

		if (cg.time > p->startfade)
		{
			invratio = 1 - ((cg.time - p->startfade) / (p->endtime - p->startfade));

			if (p->color == EMISIVEFADE)
			{
				float fval = invratio * invratio;

				if (fval < 0)
				{
					fval = 0;
				}
				VectorSet(color, fval, fval, fval);
			}
			invratio *= p->alpha;
		}
		else
		{
			invratio = 1 * p->alpha;
		}

		if (invratio > 1)
		{
			invratio = 1;
		}

		width  = p->width + (ratio * (p->endwidth - p->width));
		height = p->height + (ratio * (p->endheight - p->height));

		//if (p->type != P_SMOKE_IMPACT)
		{
			vec3_t temp;

			vectoangles(rforward, temp);
			p->accumroll += p->roll;
			temp[ROLL]   += p->accumroll * 0.1;
			//temp[ROLL] += p->roll * 0.1;
			AngleVectors(temp, NULL, rright2, rup2);
		}
		//else
		//{
		//VectorCopy (rright, rright2);
		//VectorCopy (rup, rup2);
		//}

		if (p->rotate)
		{
			VectorMA(org, -height, rup2, point);
			VectorMA(point, -width, rright2, point);
		}
		else
		{
			VectorMA(org, -p->height, vup, point);
			VectorMA(point, -p->width, vright, point);
		}
		VectorCopy(point, verts[0].xyz);
		verts[0].st[0]       = 0;
		verts[0].st[1]       = 0;
		verts[0].modulate[0] = (byte)(255 * color[0]);
		verts[0].modulate[1] = (byte)(255 * color[1]);
		verts[0].modulate[2] = (byte)(255 * color[2]);
		verts[0].modulate[3] = (byte)(255 * invratio);

		if (p->rotate)
		{
			VectorMA(org, -height, rup2, point);
			VectorMA(point, width, rright2, point);
		}
		else
		{
			VectorMA(org, -p->height, vup, point);
			VectorMA(point, p->width, vright, point);
		}
		VectorCopy(point, verts[1].xyz);
		verts[1].st[0]       = 0;
		verts[1].st[1]       = 1;
		verts[1].modulate[0] = (byte)(255 * color[0]);
		verts[1].modulate[1] = (byte)(255 * color[1]);
		verts[1].modulate[2] = (byte)(255 * color[2]);
		verts[1].modulate[3] = (byte)(255 * invratio);

		if (p->rotate)
		{
			VectorMA(org, height, rup2, point);
			VectorMA(point, width, rright2, point);
		}
		else
		{
			VectorMA(org, p->height, vup, point);
			VectorMA(point, p->width, vright, point);
		}
		VectorCopy(point, verts[2].xyz);
		verts[2].st[0]       = 1;
		verts[2].st[1]       = 1;
		verts[2].modulate[0] = (byte)(255 * color[0]);
		verts[2].modulate[1] = (byte)(255 * color[1]);
		verts[2].modulate[2] = (byte)(255 * color[2]);
		verts[2].modulate[3] = (byte)(255 * invratio);

		if (p->rotate)
		{
			VectorMA(org, height, rup2, point);
			VectorMA(point, -width, rright2, point);
		}
		else
		{
			VectorMA(org, p->height, vup, point);
			VectorMA(point, -p->width, vright, point);
		}
		VectorCopy(point, verts[3].xyz);
		verts[3].st[0]       = 1;
		verts[3].st[1]       = 0;
		verts[3].modulate[0] = (byte)(255 * color[0]);
		verts[3].modulate[1] = (byte)(255 * color[1]);
		verts[3].modulate[2] = (byte)(255 * color[2]);
		verts[3].modulate[3] = (byte)(255 * invratio);

	}
	break;
	case P_BLEED:
	{
		vec3_t point, rr, ru, rotate_ang;
		float  alpha = p->alpha;

		if (p->roll)
		{
			vectoangles(cg.refdef_current->viewaxis[0], rotate_ang);
			rotate_ang[ROLL] += p->roll;
			AngleVectors(rotate_ang, NULL, rr, ru);
		}
		else
		{
			VectorCopy(vup, ru);
			VectorCopy(vright, rr);
		}

		VectorMA(org, -p->height, ru, point);
		VectorMA(point, -p->width, rr, point);
		VectorCopy(point, verts[0].xyz);
		verts[0].st[0]       = 0;
		verts[0].st[1]       = 0;
		verts[0].modulate[0] = 111;
		verts[0].modulate[1] = 19;
		verts[0].modulate[2] = 9;
		verts[0].modulate[3] = (byte)(255 * alpha);

		VectorMA(org, -p->height, ru, point);
		VectorMA(point, p->width, rr, point);
		VectorCopy(point, verts[1].xyz);
		verts[1].st[0]       = 0;
		verts[1].st[1]       = 1;
		verts[1].modulate[0] = 111;
		verts[1].modulate[1] = 19;
		verts[1].modulate[2] = 9;
		verts[1].modulate[3] = (byte)(255 * alpha);

		VectorMA(org, p->height, ru, point);
		VectorMA(point, p->width, rr, point);
		VectorCopy(point, verts[2].xyz);
		verts[2].st[0]       = 1;
		verts[2].st[1]       = 1;
		verts[2].modulate[0] = 111;
		verts[2].modulate[1] = 19;
		verts[2].modulate[2] = 9;
		verts[2].modulate[3] = (byte)(255 * alpha);

		VectorMA(org, p->height, ru, point);
		VectorMA(point, -p->width, rr, point);
		VectorCopy(point, verts[3].xyz);
		verts[3].st[0]       = 1;
		verts[3].st[1]       = 0;
		verts[3].modulate[0] = 111;
		verts[3].modulate[1] = 19;
		verts[3].modulate[2] = 9;
		verts[3].modulate[3] = (byte)(255 * alpha);
	}
	break;
	case P_FLAT_SCALEUP:
	{
		vec3_t color;
		float  width, height;
		float  sinR, cosR;
		float  time  = cg.time - p->time;
		float  time2 = p->endtime - p->time;
		float  ratio = time / time2;

		if (p->color == BLOODRED)
		{
			VectorSet(color, 1, 1, 1);
		}
		else
		{
			VectorSet(color, 0.5f, 0.5f, 0.5f);
		}

		width  = p->width + (ratio * (p->endwidth - p->width));
		height = p->height + (ratio * (p->endheight - p->height));

		if (width > p->endwidth)
		{
			width = p->endwidth;
		}

		if (height > p->endheight)
		{
			height = p->endheight;
		}

		sinR = height * (float)(sin(DEG2RAD(p->roll)) * M_SQRT2);
		cosR = width * (float)(cos(DEG2RAD(p->roll)) * M_SQRT2);

		VectorCopy(org, verts[0].xyz);
		verts[0].xyz[0]     -= sinR;
		verts[0].xyz[1]     -= cosR;
		verts[0].st[0]       = 0;
		verts[0].st[1]       = 0;
		verts[0].modulate[0] = (byte)(255 * color[0]);
		verts[0].modulate[1] = (byte)(255 * color[1]);
		verts[0].modulate[2] = (byte)(255 * color[2]);
		verts[0].modulate[3] = 255;

		VectorCopy(org, verts[1].xyz);
		verts[1].xyz[0]     -= cosR;
		verts[1].xyz[1]     += sinR;
		verts[1].st[0]       = 0;
		verts[1].st[1]       = 1;
		verts[1].modulate[0] = verts[0].modulate[0];
		verts[1].modulate[1] = verts[0].modulate[1];
		verts[1].modulate[2] = verts[0].modulate[2];
		verts[1].modulate[3] = verts[0].modulate[3];

		VectorCopy(org, verts[2].xyz);
		verts[2].xyz[0]     += sinR;
		verts[2].xyz[1]     += cosR;
		verts[2].st[0]       = 1;
		verts[2].st[1]       = 1;
		verts[2].modulate[0] = verts[0].modulate[0];
		verts[2].modulate[1] = verts[0].modulate[1];
		verts[2].modulate[2] = verts[0].modulate[2];
		verts[2].modulate[3] = verts[0].modulate[3];

		VectorCopy(org, verts[3].xyz);
		verts[3].xyz[0]     += cosR;
		verts[3].xyz[1]     -= sinR;
		verts[3].st[0]       = 1;
		verts[3].st[1]       = 0;
		verts[3].modulate[0] = verts[0].modulate[0];
		verts[3].modulate[1] = verts[0].modulate[1];
		verts[3].modulate[2] = verts[0].modulate[2];
		verts[3].modulate[3] = verts[0].modulate[3];
	}
	break;
	case P_FLAT:
	{
		VectorCopy(org, verts[0].xyz);
		verts[0].xyz[0]     -= p->height;
		verts[0].xyz[1]     -= p->width;
		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] = 255;

		VectorCopy(org, verts[1].xyz);
		verts[1].xyz[0]     -= p->height;
		verts[1].xyz[1]     += p->width;
		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] = 255;

		VectorCopy(org, verts[2].xyz);
		verts[2].xyz[0]     += p->height;
		verts[2].xyz[1]     += p->width;
		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] = 255;

		VectorCopy(org, verts[3].xyz);
		verts[3].xyz[0]     += p->height;
		verts[3].xyz[1]     -= p->width;
		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] = 255;
	}
	break;
	case P_ANIM:
	case P_DLIGHT_ANIM:
	{
		vec3_t point, rr, ru, rotate_ang;
		float  width, height;
		float  time = cg.time - p->time;
		float  time2 = p->endtime - p->time;
		float  ratio = time / time2;
		int    i, j;

		if (ratio >= 1)
		{
			ratio = 0.9999f;
		}
		else if (ratio < 0)
		{
			// make sure that ratio isn't negative or
			// we'll walk out of bounds when j is calculated below
			ratio = 0.0001f;
		}

		width  = p->width + (ratio * (p->endwidth - p->width));
		height = p->height + (ratio * (p->endheight - p->height));

		// add dlight if necessary
		if (p->type == P_DLIGHT_ANIM)
		{
			// fixme: support arbitrary color
			trap_R_AddLightToScene(org, 320,        //%	1.5 * (width > height ? width : height),
			                       1.25f * (1.0f - ratio), 1.0f, 0.95f, 0.85f, 0, 0);
		}

		// if we are "inside" this sprite, don't draw
		if (VectorDistanceSquared(cg.snap->ps.origin, org) < Square(width / 1.5f))
		{
			return;
		}

		i          = p->shaderAnim;
		j          = (int)floor((double)ratio * shaderAnimCounts[p->shaderAnim]);
		p->pshader = shaderAnims[i][j];

		if (p->roll)
		{
			vectoangles(cg.refdef_current->viewaxis[0], rotate_ang);
			rotate_ang[ROLL] += p->roll;
			AngleVectors(rotate_ang, NULL, rr, ru);
		}

		if (p->roll)
		{
			VectorMA(org, -height, ru, point);
			VectorMA(point, -width, rr, point);
		}
		else
		{
			VectorMA(org, -height, vup, point);
			VectorMA(point, -width, vright, point);
		}
		VectorCopy(point, 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] = 255;

		if (p->roll)
		{
			VectorMA(point, 2 * height, ru, point);
		}
		else
		{
			VectorMA(point, 2 * height, vup, point);
		}
		VectorCopy(point, 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] = 255;

		if (p->roll)
		{
			VectorMA(point, 2 * width, rr, point);
		}
		else
		{
			VectorMA(point, 2 * width, vright, point);
		}
		VectorCopy(point, 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] = 255;

		if (p->roll)
		{
			VectorMA(point, -2 * height, ru, point);
		}
		else
		{
			VectorMA(point, -2 * height, vup, point);
		}
		VectorCopy(point, 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] = 255;
	}
	break;
	default:
		break;
	}

	if (!cg_wolfparticles.integer)
	{
		return;
	}

	if (!p->pshader)
	{
		CG_Printf("CG_AddParticleToScene type %d p->pshader == ZERO\n", p->type);
		return;
	}

	if (p->type == P_WEATHER || p->type == P_WEATHER_TURBULENT || p->type == P_WEATHER_FLURRY)
	{
		trap_R_AddPolyToScene(p->pshader, 3, TRIverts);
	}
	else
	{
		trap_R_AddPolyToScene(p->pshader, 4, verts);
	}
}
Пример #29
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);
		}
	}

}
Пример #30
0
void CG_Spotlight( centity_t *cent, float *color, vec3_t realstart, vec3_t lightDir, int segs, float range, int startWidth, float coneAngle, int flags ) {
	int i, j;
	vec3_t start, traceEnd, proj;
	vec3_t right, up;
	vec3_t v1, v2;
	vec3_t startvec, endvec;        // the vectors to rotate around lightDir to create the circles
	vec3_t conevec;
	vec3_t start_points[MAX_SPOT_SEGS], end_points[MAX_SPOT_SEGS];
	vec3_t coreright;
	polyVert_t verts[MAX_SPOT_SEGS * 4]; // x4 for 4 verts per poly
	polyVert_t plugVerts[MAX_SPOT_SEGS];
	vec3_t endCenter;
	polyVert_t coreverts[4];
	trace_t tr;
	float alpha;
	float radius = 0.0; // TTimo might be used uninitialized
	float coreEndRadius;
	qboolean capStart = qtrue;
	float hitDist;          // the actual distance of the trace impact	(0 is no hit)
	float beamLen;          // actual distance of the drawn beam
	float endAlpha    = 0.0;
	vec4_t colorNorm;       // normalized color vector
	refEntity_t ent;
	vec3_t angles;

	VectorCopy( realstart, start );

	// normalize color
	colorNorm[3] = 0;   // store normalize multiplier in alpha index
	for ( i = 0; i < 3; i++ ) {
		if ( color[i] > colorNorm[3] ) {
			colorNorm[3] = color[i];    // find largest color value in RGB
		}
	}

	if ( colorNorm[3] != 1 ) {     // it needs to be boosted
		VectorMA( color, 1.0 / colorNorm[3], color, colorNorm );    // FIXME: div by 0
	} else {
		VectorCopy( color, colorNorm );
	}
	colorNorm[3] = color[3];


	if ( flags & SL_NOSTARTCAP ) {
		capStart = qfalse;
	}

	if ( startWidth == 0 ) {   // cone, not cylinder
		capStart = qfalse;
	}

	if ( flags & SL_LOCKTRACETORANGE ) {
		VectorMA( start, range, lightDir, traceEnd );           // trace out to 'range'
	} else {
		VectorMA( start, MAX_SPOT_RANGE, lightDir, traceEnd );  // trace all the way out to max dist
	}

	// first trace to see if anything is hit
	if ( flags & SL_NOTRACE ) {
		tr.fraction = 1.0;  // force no hit
	} else {
		if ( flags & SL_TRACEWORLDONLY ) {
			CG_Trace( &tr, start, NULL, NULL, traceEnd, -1, CONTENTS_SOLID );
		} else {
			CG_Trace( &tr, start, NULL, NULL, traceEnd, -1, MASK_SHOT );
		}
//		CG_Trace( &tr, start, NULL, NULL, traceEnd, -1, MASK_ALL &~(CONTENTS_MONSTERCLIP|CONTENTS_AREAPORTAL|CONTENTS_CLUSTERPORTAL));
	}


	if ( tr.fraction < 1.0 ) {
		hitDist = beamLen = MAX_SPOT_RANGE * tr.fraction;
		if ( beamLen > range ) {
			beamLen = range;
		}
	} else {
		hitDist = 0;
		beamLen = range;
	}


	if ( flags & SL_LOCKUV ) {
		if ( beamLen < range ) {
			endAlpha = 255.0f * ( color[3] - ( color[3] * beamLen / range ) );
		}
	}


	if ( segs >= MAX_SPOT_SEGS ) {
		segs = MAX_SPOT_SEGS - 1;
	}

	// TODO: adjust segs based on r_lodbias
	// TODO: move much of this to renderer


// model at base
	if ( cent->currentState.modelindex ) {
		memset( &ent, 0, sizeof( ent ) );
		ent.frame = 0;
		ent.oldframe = 0;
		ent.backlerp = 0;
		VectorCopy( cent->lerpOrigin, ent.origin );
		VectorCopy( cent->lerpOrigin, ent.oldorigin );
		ent.hModel = cgs.gameModels[cent->currentState.modelindex];
		//	AnglesToAxis( cent->lerpAngles, ent.axis );
		vectoangles( lightDir, angles );
		AnglesToAxis( angles, ent.axis );
		trap_R_AddRefEntityToScene( &ent );
		memcpy( &cent->refEnt, &ent, sizeof( refEntity_t ) );

		// push start out a bit so the beam fits to the front of the base model
		VectorMA( start, 14, lightDir, start );
	}

//// BEAM

	PerpendicularVector( up, lightDir );
	CrossProduct( lightDir, up, right );

	// find first vert of the start
	VectorScale( right, startWidth, startvec );
	// find the first vert of the end
	RotatePointAroundVector( conevec, up, lightDir, -coneAngle );
	VectorMA( startvec, beamLen, conevec, endvec );   // this applies the offset of the start diameter before finding the end points

	VectorScale( lightDir, beamLen, endCenter );
	VectorSubtract( endCenter, endvec, coreverts[3].xyz );    // get a vector of the radius out at the end for the core to use
	coreEndRadius = VectorLength( coreverts[3].xyz );
#define CORESCALE 0.6f

//
//	generate the flat beam 'core'
//
	if ( !( flags & SL_NOCORE ) ) {
		VectorSubtract( start, cg.refdef.vieworg, v1 );
		VectorNormalize( v1 );
		VectorSubtract( traceEnd, cg.refdef.vieworg, v2 );
		VectorNormalize( v2 );
		CrossProduct( v1, v2, coreright );
		VectorNormalize( coreright );

		memset( &coreverts[0], 0, 4 * sizeof( polyVert_t ) );
		VectorMA( start, startWidth * 0.5f, coreright, coreverts[0].xyz );
		VectorMA( start, -startWidth * 0.5f, coreright, coreverts[1].xyz );
		VectorMA( endCenter, -coreEndRadius * CORESCALE, coreright, coreverts[2].xyz );
		VectorAdd( start, coreverts[2].xyz, coreverts[2].xyz );
		VectorMA( endCenter, coreEndRadius * CORESCALE, coreright, coreverts[3].xyz );
		VectorAdd( start, coreverts[3].xyz, coreverts[3].xyz );

		for ( i = 0; i < 4; i++ ) {
			coreverts[i].modulate[0] = color[0] * 200.0f;
			coreverts[i].modulate[1] = color[1] * 200.0f;
			coreverts[i].modulate[2] = color[2] * 200.0f;
			coreverts[i].modulate[3] = color[3] * 200.0f;
			if ( i > 1 ) {
				coreverts[i].modulate[3] = 0;
			}
		}

		trap_R_AddPolyToScene( cgs.media.spotLightBeamShader, 4, &coreverts[0] );
	}


//
// generate the beam cylinder
//



	for ( i = 0; i <= segs; i++ ) {
		RotatePointAroundVector( start_points[i], lightDir, startvec, ( 360.0f / (float)segs ) * i );
		VectorAdd( start_points[i], start, start_points[i] );

		RotatePointAroundVector( end_points[i], lightDir, endvec, ( 360.0f / (float)segs ) * i );
		VectorAdd( end_points[i], start, end_points[i] );
	}

	for ( i = 0; i < segs; i++ ) {

		j = ( i * 4 );

		VectorCopy( start_points[i], verts[( i * 4 )].xyz );
		verts[j].st[0]  = 0;
		verts[j].st[1]  = 1;
		verts[j].modulate[0] = color[0] * 255.0f;
		verts[j].modulate[1] = color[1] * 255.0f;
		verts[j].modulate[2] = color[2] * 255.0f;
		verts[j].modulate[3] = color[3] * 255.0f;
		j++;

		VectorCopy( end_points[i], verts[j].xyz );
		verts[j].st[0]  = 0;
		verts[j].st[1]  = 0;
		verts[j].modulate[0] = color[0] * 255.0f;
		verts[j].modulate[1] = color[1] * 255.0f;
		verts[j].modulate[2] = color[2] * 255.0f;
		verts[j].modulate[3] = endAlpha;
		j++;

		VectorCopy( end_points[i + 1], verts[j].xyz );
		verts[j].st[0]  = 1;
		verts[j].st[1]  = 0;
		verts[j].modulate[0] = color[0] * 255.0f;
		verts[j].modulate[1] = color[1] * 255.0f;
		verts[j].modulate[2] = color[2] * 255.0f;
		verts[j].modulate[3] = endAlpha;
		j++;

		VectorCopy( start_points[i + 1], verts[j].xyz );
		verts[j].st[0]  = 1;
		verts[j].st[1]  = 1;
		verts[j].modulate[0] = color[0] * 255.0f;
		verts[j].modulate[1] = color[1] * 255.0f;
		verts[j].modulate[2] = color[2] * 255.0f;
		verts[j].modulate[3] = color[3] * 255.0f;

		if ( capStart ) {
			VectorCopy( start_points[i], plugVerts[i].xyz );
			plugVerts[i].st[0]  = 0;
			plugVerts[i].st[1]  = 0;
			plugVerts[i].modulate[0] = color[0] * 255.0f;
			plugVerts[i].modulate[1] = color[1] * 255.0f;
			plugVerts[i].modulate[2] = color[2] * 255.0f;
			plugVerts[i].modulate[3] = color[3] * 255.0f;
		}
	}

	trap_R_AddPolysToScene( cgs.media.spotLightBeamShader, 4, &verts[0], segs );


	// plug up the start circle
	if ( capStart ) {
		trap_R_AddPolyToScene( cgs.media.spotLightBeamShader, segs, &plugVerts[0] );
	}


	// show the endpoint

	if ( !( flags & SL_NOIMPACT ) ) {
		if ( hitDist ) {
			VectorMA( startvec, hitDist, conevec, endvec );

			alpha = 0.3f;
			radius = coreEndRadius * ( hitDist / beamLen );

			VectorNegate( lightDir, proj );
			CG_ImpactMark( cgs.media.spotLightShader, tr.endpos, proj, 0, colorNorm[0], colorNorm[1], colorNorm[2], alpha, qfalse, radius, qtrue, -1 );
		}
	}



	// add d light at end
	if ( !( flags & SL_NODLIGHT ) ) {
		vec3_t dlightLoc;
//		VectorMA(tr.endpos, -60, lightDir, dlightLoc);	// back away from the hit
//		trap_R_AddLightToScene(dlightLoc, 200, colorNorm[0], colorNorm[1], colorNorm[2], 0);	// ,REF_JUNIOR_DLIGHT);
		VectorMA( tr.endpos, 0, lightDir, dlightLoc );    // back away from the hit
//		trap_R_AddLightToScene(dlightLoc, radius*2, colorNorm[0], colorNorm[1], colorNorm[2], 0);	// ,REF_JUNIOR_DLIGHT);
		trap_R_AddLightToScene( dlightLoc, radius * 2, 0.3, 0.3, 0.3, 0 );  // ,REF_JUNIOR_DLIGHT);
	}



	// draw flare at source
	if ( !( flags & SL_NOFLARE ) ) {
		qboolean lightInEyes = qfalse;
		vec3_t camloc, dirtolight;
		float dot, deg, dist;
		float flarescale = 0.0;       // TTimo: might be used uninitialized

		// get camera position and direction to lightsource
		VectorCopy( cg.snap->ps.origin, camloc );
		camloc[2] += cg.snap->ps.viewheight;
		VectorSubtract( start, camloc, dirtolight );
		dist = VectorNormalize( dirtolight );

		// first use dot to determine if it's facing the camera
		dot = DotProduct( lightDir, dirtolight );

		// it's facing the camera, find out how closely and trace to see if the source can be seen

		deg = RAD2DEG( M_PI - acos( dot ) );
		if ( deg <= 35 ) { // start flare a bit before the camera gets inside the cylinder
			lightInEyes = qtrue;
			flarescale = 1 - ( deg / 35 );
		}

		if ( lightInEyes ) {   // the dot check succeeded, now do a trace
			CG_Trace( &tr, start, NULL, NULL, camloc, -1, MASK_ALL & ~( CONTENTS_MONSTERCLIP | CONTENTS_AREAPORTAL | CONTENTS_CLUSTERPORTAL ) );
			if ( tr.fraction != 1 ) {
				lightInEyes = qfalse;
			}

		}

		if ( lightInEyes ) {
			float coronasize = flarescale;
			if ( dist < 512 ) { // make even bigger if you're close enough
				coronasize *= ( 512.0f / dist );
			}

			trap_R_AddCoronaToScene( start, colorNorm[0], colorNorm[1], colorNorm[2], coronasize, cent->currentState.number, qtrue );
		} else {
			// even though it's off, still need to add it, but turned off so it can fade in/out properly
			trap_R_AddCoronaToScene( start, colorNorm[0], colorNorm[1], colorNorm[2], 0, cent->currentState.number, qfalse );
		}
	}

}