void FXTrail::Draw( void )
{
	vec3_t		lineDir, cross, viewDir;
	polyVert_t	verts[4];
	float		scale;

	VectorSubtract( m_oldorigin, m_origin, lineDir );
	VectorSubtract( m_oldorigin, cg.refdef.vieworg, viewDir );
	CrossProduct( lineDir, viewDir, cross );
	VectorNormalize( cross );

	scale = m_scale * 0.5;

	//Construct the oriented quad
	VectorMA( m_origin, -scale, cross, verts[0].xyz );
	verts[0].st[0] = 0.0f;
	verts[0].st[1] = 0.0f;
	verts[0].modulate[0] = m_RGB[0] * 255;
	verts[0].modulate[1] = m_RGB[1] * 255;
	verts[0].modulate[2] = m_RGB[2] * 255;

	VectorMA( m_origin, scale, cross, verts[1].xyz );
	verts[1].st[0] = 1.0f;
	verts[1].st[1] = 0.0f;
	verts[1].modulate[0] = m_RGB[0] * 255;
	verts[1].modulate[1] = m_RGB[1] * 255;
	verts[1].modulate[2] = m_RGB[2] * 255;

	VectorMA( m_oldorigin, scale, cross, verts[2].xyz );
	verts[2].st[0] = 1.0f;
	verts[2].st[1] = 1.0f;
	verts[2].modulate[0] = m_RGB[0] * 255;
	verts[2].modulate[1] = m_RGB[1] * 255;
	verts[2].modulate[2] = m_RGB[2] * 255;

	VectorMA( m_oldorigin, -scale, cross, verts[3].xyz );
	verts[3].st[0] = 0.0f;
	verts[3].st[1] = 1.0f;
	verts[3].modulate[0] = m_RGB[0] * 255;
	verts[3].modulate[1] = m_RGB[1] * 255;
	verts[3].modulate[2] = m_RGB[2] * 255;

	if ( m_flags & FXF_USE_ALPHA_CHAN )
	{
		verts[0].modulate[3] =
		verts[1].modulate[3] =
		verts[2].modulate[3] =
		verts[3].modulate[3] = (byte)(m_alpha * 255);
	}
	else
	{
		verts[0].modulate[3] =
		verts[1].modulate[3] =
		verts[2].modulate[3] =
		verts[3].modulate[3] = 255;
	}

	cgi_R_AddPolyToScene( m_shader, 4, verts );
}
Esempio n. 2
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 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 
			{
				float f = (float)t / MARK_FADE_TIME;
				for ( j = 0 ; j < mp->poly.numVerts ; j++ ) {
					mp->verts[j].modulate[0] = mp->color[0] * f;
					mp->verts[j].modulate[1] = mp->color[1] * f;
					mp->verts[j].modulate[2] = mp->color[2] * f;
				}
			}
		}
		else
		{
			for ( j = 0 ; j < mp->poly.numVerts ; j++ ) {
				mp->verts[j].modulate[0] = mp->color[0];
				mp->verts[j].modulate[1] = mp->color[1];
				mp->verts[j].modulate[2] = mp->color[2];
			}
		}


		cgi_R_AddPolyToScene( mp->markShader, mp->poly.numVerts, mp->verts );
	}
}
void FXTri::Draw( void )
{
	polyVert_t	verts[3];

	//Construct the tri
	VectorCopy( m_origin, verts[0].xyz );
	verts[0].st[0] = 0.0f;
	verts[0].st[1] = 0.0f;
	verts[0].modulate[0] = m_RGB[0] * 255;
	verts[0].modulate[1] = m_RGB[1] * 255;
	verts[0].modulate[2] = m_RGB[2] * 255;

	VectorCopy( m_origin2, verts[1].xyz );
	verts[1].st[0] = 1.0f;
	verts[1].st[1] = 0.0f;
	verts[1].modulate[0] = m_RGB[0] * 255;
	verts[1].modulate[1] = m_RGB[1] * 255;
	verts[1].modulate[2] = m_RGB[2] * 255;

	VectorCopy( m_origin3, verts[2].xyz );
	verts[2].st[0] = 1.0f;
	verts[2].st[1] = 1.0f;
	verts[2].modulate[0] = m_RGB[0] * 255;
	verts[2].modulate[1] = m_RGB[1] * 255;
	verts[2].modulate[2] = m_RGB[2] * 255;

	if ( m_flags & FXF_USE_ALPHA_CHAN )
	{
		verts[0].modulate[3] = 
		verts[1].modulate[3] = 
		verts[2].modulate[3] = (byte)(m_alpha * 255);
	}
	else
	{
		verts[0].modulate[3] = 
		verts[1].modulate[3] = 
		verts[2].modulate[3] = 255;
	}

	cgi_R_AddPolyToScene( m_shader, 3, verts );
}
void FXParticle::Draw( void )
{
	polyVert_t	verts[4];
	vec3_t		axis[3];
	float		scale;
	int			i;

	if ( m_flags & FXF_NODRAW )
		return;

	scale = m_scale * 0.5f;
	
	for ( i = 0; i < 3; i++ )
		VectorCopy( cg.refdef.viewaxis[i], axis[i] );	

	//This is done to spare non-rolling particles the odd angle snapping <?>
	if (m_roll)
		RotateAroundDirection( axis, m_roll );
	
	for ( i = 0; i < 4; i++ )
	{	
		VectorMA( m_origin,		sprite_template[i][0] * scale, axis[1], verts[i].xyz );
		VectorMA( verts[i].xyz, sprite_template[i][1] * scale, axis[2], verts[i].xyz );

		//Setup the UVs
		verts[i].st[0] = sprite_texture_template[i][0];
		verts[i].st[1] = sprite_texture_template[i][1];

		//Setup the vertex modulation
		verts[i].modulate[0] = (byte)(m_RGB[0] * 255);
		verts[i].modulate[1] = (byte)(m_RGB[1] * 255);
		verts[i].modulate[2] = (byte)(m_RGB[2] * 255);
		if ( m_flags & FXF_USE_ALPHA_CHAN )
			verts[i].modulate[3] = (byte)(m_alpha * 255);
		else
			verts[i].modulate[3] = 255;
	}

	//Add it into the renderer
	cgi_R_AddPolyToScene( m_shader, 4, verts );
}
Esempio n. 5
0
// create a sprite that doesn't use a refEnt.  Currently only for use with the DebugNav drawing so it doesn't have to use fx
//------------------------------------------
static void CG_AddSprite( localEntity_t *le )
{
	polyVert_t	verts[4];

	VectorCopy( le->refEntity.origin, verts[0].xyz );
	VectorMA( verts[0].xyz, -le->radius, cg.refdef.viewaxis[2], verts[0].xyz );
	VectorMA( verts[0].xyz, -le->radius, cg.refdef.viewaxis[1], verts[0].xyz );
	verts[0].st[0] = 0;
	verts[0].st[1] = 0;

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

	VectorCopy( le->refEntity.origin, verts[1].xyz );
	VectorMA( verts[1].xyz, -le->radius, cg.refdef.viewaxis[2], verts[1].xyz );
	VectorMA( verts[1].xyz, le->radius, cg.refdef.viewaxis[1], verts[1].xyz );
	verts[1].st[0] = 0;
	verts[1].st[1] = 1;

	VectorCopy( le->refEntity.origin, verts[2].xyz );
	VectorMA( verts[2].xyz, le->radius, cg.refdef.viewaxis[2], verts[2].xyz );
	VectorMA( verts[2].xyz, le->radius, cg.refdef.viewaxis[1], verts[2].xyz );
	verts[2].st[0] = 1;
	verts[2].st[1] = 1;

	VectorCopy( le->refEntity.origin, verts[3].xyz );
	VectorMA( verts[3].xyz, le->radius, cg.refdef.viewaxis[2], verts[3].xyz );
	VectorMA( verts[3].xyz, -le->radius, cg.refdef.viewaxis[1], verts[3].xyz );
	verts[3].st[0] = 1;
	verts[3].st[1] = 0;

	cgi_R_AddPolyToScene( le->refEntity.customShader, 4, verts );
}
Esempio n. 6
0
// create a quad that doesn't use a refEnt.  Currently only for use with the DebugNav drawing so it doesn't have to use fx
//------------------------------------------
static void CG_AddQuad( localEntity_t *le )
{
	polyVert_t	verts[4];

	VectorCopy( le->refEntity.origin, verts[0].xyz );
	verts[0].xyz[0] -= le->radius;
	verts[0].xyz[1] -= le->radius;
	verts[0].st[0] = 0;
	verts[0].st[1] = 0;

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

	VectorCopy( le->refEntity.origin, verts[1].xyz );
	verts[1].xyz[0] -= le->radius;
	verts[1].xyz[1] += le->radius;
	verts[1].st[0] = 0;
	verts[1].st[1] = 1;

	VectorCopy( le->refEntity.origin, verts[2].xyz );
	verts[2].xyz[0] += le->radius;
	verts[2].xyz[1] += le->radius;
	verts[2].st[0] = 1;
	verts[2].st[1] = 1;

	VectorCopy( le->refEntity.origin, verts[3].xyz );
	verts[3].xyz[0] += le->radius;
	verts[3].xyz[1] -= le->radius;
	verts[3].st[0] = 1;
	verts[3].st[1] = 0;

	cgi_R_AddPolyToScene( le->refEntity.customShader, 4, verts );
}
void FXQuad::Draw( void )
{
	polyVert_t	verts[NUM_QUADVERTS];
	vec3_t		vr, vu;
	vec3_t		axis[3];
	float		scale;
	int			i;

	scale = m_scale * 0.5f;

	MakeNormalVectors( m_normal, vr, vu );
	VectorCopy( m_normal, axis[0] );
	VectorCopy( vr, axis[1] );
	VectorCopy( vu, axis[2] );

	RotateAroundDirection( axis, m_roll );

	//Construct the quad
	for ( i = 0; i < NUM_QUADVERTS; i++ )
	{
		VectorMA( m_origin,		quad_template[i][0] * ( scale ), axis[1], verts[i].xyz );
		VectorMA( verts[i].xyz, quad_template[i][1] * ( scale ), axis[2], verts[i].xyz );
		
		verts[i].modulate[0] = m_RGB[0] * 255;
		verts[i].modulate[1] = m_RGB[1] * 255;
		verts[i].modulate[2] = m_RGB[2] * 255;
		if ( m_flags & FXF_USE_ALPHA_CHAN )
			verts[i].modulate[3] = (byte)(m_alpha * 255);
		else
			verts[i].modulate[3] = 255;
		
		verts[i].st[0] = quad_st_template[i][0];
		verts[i].st[1] = quad_st_template[i][1];
	}

	cgi_R_AddPolyToScene( m_shader, NUM_QUADVERTS, verts );
}
Esempio n. 8
0
//------------------------------------------------------
void SFxHelper::AddPolyToScene( int shader, int count, polyVert_t *verts )
{
	cgi_R_AddPolyToScene( shader, count, verts );
}
Esempio n. 9
0
//----------------------------
inline void CBezier::DrawSegment( vec3_t start, vec3_t end, float texcoord1, float texcoord2 )
{
	vec3_t			lineDir, cross, viewDir;
	static vec3_t	lastEnd[2];
	polyVert_t		verts[4];
	float			scale;

	VectorSubtract( end, start, lineDir );
	VectorSubtract( end, cg.refdef.vieworg, viewDir );
	CrossProduct( lineDir, viewDir, cross );
	VectorNormalize( cross );

	scale = mRefEnt.radius * 0.5f;

	//Construct the oriented quad
	if ( mInit )
	{
		VectorCopy( lastEnd[0], verts[0].xyz );
		VectorCopy( lastEnd[1], verts[1].xyz );
	}
	else
	{
		VectorMA( start, -scale, cross, verts[0].xyz );
		VectorMA( start, scale, cross, verts[1].xyz );
	}

	verts[0].st[0] = 0.0f;
	verts[0].st[1] = texcoord1;

	verts[0].modulate[0] = mRefEnt.shaderRGBA[0] * ( 1.0f - texcoord1 );
	verts[0].modulate[1] = mRefEnt.shaderRGBA[1] * ( 1.0f - texcoord1 );
	verts[0].modulate[2] = mRefEnt.shaderRGBA[2] * ( 1.0f - texcoord1 );
	verts[0].modulate[3] = mRefEnt.shaderRGBA[3];

	verts[1].st[0] = 1.0f;
	verts[1].st[1] = texcoord1;
	verts[1].modulate[0] = mRefEnt.shaderRGBA[0] * ( 1.0f - texcoord1 );
	verts[1].modulate[1] = mRefEnt.shaderRGBA[1] * ( 1.0f - texcoord1 );
	verts[1].modulate[2] = mRefEnt.shaderRGBA[2] * ( 1.0f - texcoord1 );
	verts[1].modulate[3] = mRefEnt.shaderRGBA[3];

	if ( texcoord1 == 0.0f )
	{
		verts[0].modulate[0] = 0;
		verts[0].modulate[1] = 0;
		verts[0].modulate[2] = 0;
		verts[0].modulate[3] = 0;
		verts[1].modulate[0] = 0;
		verts[1].modulate[1] = 0;
		verts[1].modulate[2] = 0;
		verts[1].modulate[3] = 0;
	}

	VectorMA( end, scale, cross, verts[2].xyz );
	verts[2].st[0] = 1.0f;
	verts[2].st[1] = texcoord2;
	verts[2].modulate[0] = mRefEnt.shaderRGBA[0] * ( 1.0f - texcoord2 );
	verts[2].modulate[1] = mRefEnt.shaderRGBA[1] * ( 1.0f - texcoord2 );
	verts[2].modulate[2] = mRefEnt.shaderRGBA[2] * ( 1.0f - texcoord2 );
	verts[2].modulate[3] = mRefEnt.shaderRGBA[3];

	VectorMA( end, -scale, cross, verts[3].xyz );
	verts[3].st[0] = 0.0f;
	verts[3].st[1] = texcoord2;
	verts[3].modulate[0] = mRefEnt.shaderRGBA[0] * ( 1.0f - texcoord2 );
	verts[3].modulate[1] = mRefEnt.shaderRGBA[1] * ( 1.0f - texcoord2 );
	verts[3].modulate[2] = mRefEnt.shaderRGBA[2] * ( 1.0f - texcoord2 );
	verts[3].modulate[3] = mRefEnt.shaderRGBA[3];

	cgi_R_AddPolyToScene( mRefEnt.customShader, 4, verts );

	VectorCopy( verts[2].xyz, lastEnd[1] );
	VectorCopy( verts[3].xyz, lastEnd[0] );

	mInit = true;
}
Esempio n. 10
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 ) {
	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 ( radius <= 0 ) {
		CG_Error( "CG_ImpactMark called with <= 0 radius" );
	}

	// 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 = cgi_CM_MarkFragments( 4, (const float (*)[3])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 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;
			for ( int k = 0; k < 4; k++ ) {
				v->modulate[k] = colors[k];
			}
		}

		// if it is a temporary (shadow) mark, add it immediately and forget about it
		if ( temporary ) {
			cgi_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] = colors[0];//red;
		mark->color[1] = colors[1];//green;
		mark->color[2] = colors[2];//blue;
		mark->color[3] = colors[3];//alpha;
		memcpy( mark->verts, verts, mf->numPoints * sizeof( verts[0] ) );
	}
}
void FXLine::Draw( void )
{
	vec3_t		lineDir, cross, viewDir, neworg;
	polyVert_t	verts[4];
	float		scale;

	VectorSubtract( m_origin2, m_origin, lineDir );
	VectorSubtract( m_origin2, cg.refdef.vieworg, viewDir );
	CrossProduct( lineDir, viewDir, cross );
	VectorNormalize( cross );

	scale = m_scale * 0.5;

	//Construct the oriented quad
	VectorMA( m_origin, -scale, cross, verts[0].xyz );
	verts[0].st[0] = 0.0f;
	verts[0].st[1] = 0.0f;
	verts[0].modulate[0] = m_RGB[0] * 255;
	verts[0].modulate[1] = m_RGB[1] * 255;
	verts[0].modulate[2] = m_RGB[2] * 255;

	VectorMA( m_origin, scale, cross, verts[1].xyz );
	verts[1].st[0] = 1.0f;
	verts[1].st[1] = 0.0f;
	verts[1].modulate[0] = m_RGB[0] * 255;
	verts[1].modulate[1] = m_RGB[1] * 255;
	verts[1].modulate[2] = m_RGB[2] * 255;

	VectorMA( m_origin2, scale, cross, verts[2].xyz );
	verts[2].st[0] = 1.0f;
	verts[2].st[1] = m_stScale;
	verts[2].modulate[0] = m_RGB[0] * 255;
	verts[2].modulate[1] = m_RGB[1] * 255;
	verts[2].modulate[2] = m_RGB[2] * 255;

	VectorMA( m_origin2, -scale, cross, verts[3].xyz );
	verts[3].st[0] = 0.0f;
	verts[3].st[1] = m_stScale;
	verts[3].modulate[0] = m_RGB[0] * 255;
	verts[3].modulate[1] = m_RGB[1] * 255;
	verts[3].modulate[2] = m_RGB[2] * 255;

	if ( m_flags & FXF_USE_ALPHA_CHAN )
	{
		verts[0].modulate[3] =
		verts[1].modulate[3] =
		verts[2].modulate[3] =
		verts[3].modulate[3] = (byte)(m_alpha * 255);
	}
	else
	{
		verts[0].modulate[3] =
		verts[1].modulate[3] =
		verts[2].modulate[3] =
		verts[3].modulate[3] = 255;
	}

	cgi_R_AddPolyToScene( m_shader, 4, verts );

	//Cap the lines
	if ( m_flags & FXF_DRAWCAPS )
	{
		//Construct an oriented quad for the endcap
		VectorMA( m_origin, scale, cross, verts[0].xyz );
		verts[0].st[0] = 0.0f;
		verts[0].st[1] = 0.02f;
		verts[0].modulate[0] = m_RGB[0] * 255;
		verts[0].modulate[1] = m_RGB[1] * 255;
		verts[0].modulate[2] = m_RGB[2] * 255;

		VectorMA( m_origin, -scale, cross, verts[1].xyz );
		verts[1].st[0] = 1.0f;
		verts[1].st[1] = 0.1f;
		verts[1].modulate[0] = m_RGB[0] * 255;
		verts[1].modulate[1] = m_RGB[1] * 255;
		verts[1].modulate[2] = m_RGB[2] * 255;

		VectorNormalize( lineDir );
		VectorMA( m_origin, -scale * 2, lineDir, neworg );
		VectorMA( neworg, -scale, cross, verts[2].xyz );
		verts[2].st[0] = 1.0f;
		verts[2].st[1] = 0.9f;
		verts[2].modulate[0] = m_RGB[0] * 255;
		verts[2].modulate[1] = m_RGB[1] * 255;
		verts[2].modulate[2] = m_RGB[2] * 255;

		VectorMA( neworg, scale, cross, verts[3].xyz );
		verts[3].st[0] = 0.0f;
		verts[3].st[1] = 0.9f;
		verts[3].modulate[0] = m_RGB[0] * 255;
		verts[3].modulate[1] = m_RGB[1] * 255;
		verts[3].modulate[2] = m_RGB[2] * 255;

		if ( m_flags & FXF_USE_ALPHA_CHAN )
		{
			verts[0].modulate[3] =
			verts[1].modulate[3] =
			verts[2].modulate[3] =
			verts[3].modulate[3] = (byte)(m_alpha * 255);
		}
		else
		{
			verts[0].modulate[3] =
			verts[1].modulate[3] =
			verts[2].modulate[3] =
			verts[3].modulate[3] = 255;
		}

		cgi_R_AddPolyToScene( m_endcap_shader, 4, verts );

		//Construct an oriented quad for the endcap
		VectorMA( m_origin2, -scale, cross, verts[0].xyz );
		verts[0].st[0] = 0.0f;
		verts[0].st[1] = 0.1f;
		verts[0].modulate[0] = m_RGB[0] * 255;
		verts[0].modulate[1] = m_RGB[1] * 255;
		verts[0].modulate[2] = m_RGB[2] * 255;

		VectorMA( m_origin2, scale, cross, verts[1].xyz );
		verts[1].st[0] = 1.0f;
		verts[1].st[1] = 0.05f;
		verts[1].modulate[0] = m_RGB[0] * 255;
		verts[1].modulate[1] = m_RGB[1] * 255;
		verts[1].modulate[2] = m_RGB[2] * 255;

		VectorMA( m_origin2, scale * 2, lineDir, neworg );
		VectorMA( neworg, scale, cross, verts[2].xyz );
		verts[2].st[0] = 1.0f;
		verts[2].st[1] = 0.9f;
		verts[2].modulate[0] = m_RGB[0] * 255;
		verts[2].modulate[1] = m_RGB[1] * 255;
		verts[2].modulate[2] = m_RGB[2] * 255;

		VectorMA( neworg, -scale, cross, verts[3].xyz );
		verts[3].st[0] = 0.0f;
		verts[3].st[1] = 0.9f;
		verts[3].modulate[0] = m_RGB[0] * 255;
		verts[3].modulate[1] = m_RGB[1] * 255;
		verts[3].modulate[2] = m_RGB[2] * 255;

		if ( m_flags & FXF_USE_ALPHA_CHAN )
		{
			verts[0].modulate[3] =
			verts[1].modulate[3] =
			verts[2].modulate[3] =
			verts[3].modulate[3] = (byte)(m_alpha * 255);
		}
		else
		{
			verts[0].modulate[3] =
			verts[1].modulate[3] =
			verts[2].modulate[3] =
			verts[3].modulate[3] = 255;
		}

		cgi_R_AddPolyToScene( m_endcap_shader, 4, verts );
	}
}
inline void FXElectricity::DrawSegment( vec3_t start, vec3_t end, float scale, float tcStart, float tcEnd )
{
	vec3_t		lineDir, cross, viewDir;
	polyVert_t	verts[4];

	VectorSubtract( end, start, lineDir );
	VectorSubtract( end, cg.refdef.vieworg, viewDir );

	CrossProduct( lineDir, viewDir, cross );
	VectorNormalize( cross );

	scale *= 0.5;

	//Construct the oriented quad
	
	if ( m_init )
		VectorCopy( m_lastEnd[0], verts[0].xyz );
	else
		VectorMA( start, -scale, cross, verts[0].xyz );

	verts[0].st[0] = 0.0f;
	verts[0].st[1] = tcStart;
	verts[0].modulate[0] = m_RGB[0] * 255;
	verts[0].modulate[1] = m_RGB[1] * 255;
	verts[0].modulate[2] = m_RGB[2] * 255;

	if ( m_init )
		VectorCopy( m_lastEnd[1], verts[1].xyz );
	else
		VectorMA( start, scale, cross, verts[1].xyz );

	verts[1].st[0] = 1.0f;
	verts[1].st[1] = tcStart;
	verts[1].modulate[0] = m_RGB[0] * 255;
	verts[1].modulate[1] = m_RGB[1] * 255;
	verts[1].modulate[2] = m_RGB[2] * 255;

	VectorMA( end, scale, cross, verts[2].xyz );
	verts[2].st[0] = 1.0f;
	verts[2].st[1] = tcEnd;
	verts[2].modulate[0] = m_RGB[0] * 255;
	verts[2].modulate[1] = m_RGB[1] * 255;
	verts[2].modulate[2] = m_RGB[2] * 255;

	VectorMA( end, -scale, cross, verts[3].xyz );
	verts[3].st[0] = 0.0f;
	verts[3].st[1] = tcEnd;
	verts[3].modulate[0] = m_RGB[0] * 255;
	verts[3].modulate[1] = m_RGB[1] * 255;
	verts[3].modulate[2] = m_RGB[2] * 255;

	if ( m_flags & FXF_USE_ALPHA_CHAN )
	{
		verts[0].modulate[3] =
		verts[1].modulate[3] =
		verts[2].modulate[3] =
		verts[3].modulate[3] = (byte)(m_alpha * 255);
	}
	else
	{
		verts[0].modulate[3] =
		verts[1].modulate[3] =
		verts[2].modulate[3] =
		verts[3].modulate[3] = 255;
	}

	cgi_R_AddPolyToScene( m_shader, 4, verts );

	VectorCopy( verts[2].xyz, m_lastEnd[1] );
	VectorCopy( verts[3].xyz, m_lastEnd[0] );

	m_init = true;
}
void FXCylinder::Draw( void )
{
	polyVert_t	lower_points[NUM_CYLINDER_SEGMENTS], upper_points[NUM_CYLINDER_SEGMENTS], verts[4];
	vec3_t		vr, vu, vu2, midpoint, origin2;
	float		detail, length;
	int			i;
	int			segments;

	// allow for overriding the LOD mechanism, not recommended, but hey, flexibility is often cool...
	if ( m_flags & FXF_NO_LOD )
	{
		segments = NUM_CYLINDER_SEGMENTS;
	}
	else
	{
		//Work out the detail level of this cylinder
		VectorMA( m_origin, m_height * 0.5, m_normal, midpoint );
		VectorSubtract( midpoint, cg.refdef.vieworg, midpoint );
		length = VectorLengthSquared( midpoint );

		detail = 1 - (length / (1024.0*1024.0) );

		// FIXME: the bias doesn't really work all that great
		//Cylinder bias is simply implemented as a multiplier
		segments = NUM_CYLINDER_SEGMENTS * detail * m_bias;

		// 3 is the absolute minimum, but the pop between 3, 4 and 5 is too noticeable
		if ( segments < 7 )
		{
			segments = 7;
		}

		if ( segments > NUM_CYLINDER_SEGMENTS )
		{
			segments = NUM_CYLINDER_SEGMENTS;
		}
	}

	//Get the direction vector
	MakeNormalVectors( m_normal, vr, vu );

	VectorScale( vu, m_scale2 * 0.5, vu2 );
	VectorScale( vu, m_scale * 0.5, vu );

	VectorMA( m_origin, m_height, m_normal, origin2 );

	// Calculate the step around the cylinder
	detail = 360.0 / (float)segments;

	for ( i = 0; i < segments ; i++ )
	{
		//Upper ring
		RotatePointAroundVector( upper_points[i].xyz, m_normal, vu, detail * i );
		VectorAdd( upper_points[i].xyz, m_origin, upper_points[i].xyz );
		
		//Lower ring
		RotatePointAroundVector( lower_points[i].xyz, m_normal, vu2, detail * i );
		VectorAdd( lower_points[i].xyz, origin2, lower_points[i].xyz );
	}
	
	// Calculate the texture coords so the texture can wrap around the whole cylinder
	if ( m_flags & FXF_WRAP )
	{
		if ( m_flags & FXF_STRETCH )
			detail = 1.0f / (float)segments;
		else
			detail = m_stScale / (float)segments;
	}

	for ( i = 0; i < segments ; i++ )
	{
		int nextSegment = ( i + 1 == segments ) ? 0 : i + 1;

		if ( m_flags & FXF_WRAP )
		{
			verts[0].st[0] = detail * i;
			verts[1].st[0] = detail * i;
			verts[2].st[0] = detail * ( i + 1 );
			verts[3].st[0] = detail * ( i + 1 );
		}
		else
		{
			verts[0].st[0] = 0.0f;
			verts[1].st[0] = 0.0f;
			verts[2].st[0] = m_stScale;
			verts[3].st[0] = m_stScale;
		}

		if( m_flags & FXF_STRETCH )
		{
			verts[0].st[1] = m_stScale;
			verts[1].st[1] = 0.0f;
			verts[2].st[1] = 0.0f;
			verts[3].st[1] = m_stScale;
		}
		else
		{
			verts[0].st[1] = 1.0f;
			verts[1].st[1] = 0.0f;
			verts[2].st[1] = 0.0f;
			verts[3].st[1] = 1.0f;
		}
			
 		VectorCopy( upper_points[i].xyz, verts[0].xyz );
		
		verts[0].modulate[0] = m_RGB[0] * 255;
		verts[0].modulate[1] = m_RGB[1] * 255;
		verts[0].modulate[2] = m_RGB[2] * 255;

		VectorCopy( lower_points[i].xyz, verts[1].xyz );
		
		verts[1].modulate[0] = m_RGB[0] * 255;
		verts[1].modulate[1] = m_RGB[1] * 255;
		verts[1].modulate[2] = m_RGB[2] * 255;

		VectorCopy( lower_points[nextSegment].xyz, verts[2].xyz );
		
		verts[2].modulate[0] = m_RGB[0] * 255;
		verts[2].modulate[1] = m_RGB[1] * 255;
		verts[2].modulate[2] = m_RGB[2] * 255;

		VectorCopy( upper_points[nextSegment].xyz, verts[3].xyz );
		
		verts[3].modulate[0] = m_RGB[0] * 255;
		verts[3].modulate[1] = m_RGB[1] * 255;
		verts[3].modulate[2] = m_RGB[2] * 255;

		if ( m_flags & FXF_USE_ALPHA_CHAN )
		{
			verts[0].modulate[3] =
			verts[1].modulate[3] =
			verts[2].modulate[3] =
			verts[3].modulate[3] = (byte)(m_alpha * 255);
		}
		else
		{
			verts[0].modulate[3] =
			verts[1].modulate[3] =
			verts[2].modulate[3] =
			verts[3].modulate[3] = 255;
		}

		cgi_R_AddPolyToScene( m_shader, 4, verts );
	}
}
void FXLine2::Draw( void )
{
#if 0
	vec3_t		lineDir, cross, viewDir;
	polyVert_t	verts[4];
	float		scale, scale2;

	VectorSubtract( m_origin2, m_origin, lineDir );
	VectorSubtract( m_origin2, cg.refdef.vieworg, viewDir );
	CrossProduct( lineDir, viewDir, cross );
	VectorNormalize( cross );

	scale	= m_scale * 0.5f;
	scale2	= m_scale2 * 0.5f;

	//Construct the oriented quad
	VectorMA( m_origin, -scale, cross, verts[0].xyz );
	verts[0].st[0] = 0.0f;
	verts[0].st[1] = 0.0f;
	verts[0].modulate[0] = m_RGB[0] * 255;
	verts[0].modulate[1] = m_RGB[1] * 255;
	verts[0].modulate[2] = m_RGB[2] * 255;

	VectorMA( m_origin, scale, cross, verts[1].xyz );
	verts[1].st[0] = 1.0f;
	verts[1].st[1] = 0.0f;
	verts[1].modulate[0] = m_RGB[0] * 255;
	verts[1].modulate[1] = m_RGB[1] * 255;
	verts[1].modulate[2] = m_RGB[2] * 255;

	VectorMA( m_origin2, scale2, cross, verts[2].xyz );
	verts[2].st[0] = 1.0f;
	verts[2].st[1] = m_stScale;
	verts[2].modulate[0] = m_RGB[0] * 255;
	verts[2].modulate[1] = m_RGB[1] * 255;
	verts[2].modulate[2] = m_RGB[2] * 255;

	VectorMA( m_origin2, -scale2, cross, verts[3].xyz );
	verts[3].st[0] = 0.0f;
	verts[3].st[1] = m_stScale;
	verts[3].modulate[0] = m_RGB[0] * 255;
	verts[3].modulate[1] = m_RGB[1] * 255;
	verts[3].modulate[2] = m_RGB[2] * 255;

	if ( m_flags & FXF_USE_ALPHA_CHAN )
	{
		verts[0].modulate[3] =
		verts[1].modulate[3] =
		verts[2].modulate[3] =
		verts[3].modulate[3] = (byte)(m_alpha * 255);
	}
	else
	{
		verts[0].modulate[3] =
		verts[1].modulate[3] =
		verts[2].modulate[3] =
		verts[3].modulate[3] = 255;
	}

	cgi_R_AddPolyToScene( m_shader, 4, verts );
#else
	vec3_t		lineDir, cross, viewDir;
	polyVert_t	verts[4];
	float		scale, scale2;

	VectorSubtract( m_origin2, m_origin, lineDir );
	VectorSubtract( m_origin2, cg.refdef.vieworg, viewDir );
	CrossProduct( lineDir, viewDir, cross );
	VectorNormalize( cross );

	scale	= m_scale * 0.5f;
	scale2	= m_scale2 * 0.5f;

	if ( m_flags & FXF_USE_ALPHA_CHAN )
	{
		verts[0].modulate[3] =
		verts[1].modulate[3] =
		verts[2].modulate[3] =
		verts[3].modulate[3] = (byte)(m_alpha * 255);
	}
	else
	{
		verts[0].modulate[3] =
		verts[1].modulate[3] =
		verts[2].modulate[3] =
		verts[3].modulate[3] = 255;
	}

	//Construct the tapered, oriented quad, we have to use 3 tris to do this though
	VectorCopy( m_origin, verts[0].xyz );
	verts[0].st[0] = 0.5f;
	verts[0].st[1] = 0.0f;
	verts[0].modulate[0] = m_RGB[0] * 255;
	verts[0].modulate[1] = m_RGB[1] * 255;
	verts[0].modulate[2] = m_RGB[2] * 255;

	VectorMA( m_origin2, -scale2, cross, verts[1].xyz );
	verts[1].st[0] = 1.0f;
	verts[1].st[1] = m_stScale;
	verts[1].modulate[0] = m_RGB[0] * 255;
	verts[1].modulate[1] = m_RGB[1] * 255;
	verts[1].modulate[2] = m_RGB[2] * 255;

	VectorMA( m_origin2, scale2, cross, verts[2].xyz );
	verts[2].st[0] = 0.0f;
	verts[2].st[1] = m_stScale;
	verts[2].modulate[0] = m_RGB[0] * 255;
	verts[2].modulate[1] = m_RGB[1] * 255;
	verts[2].modulate[2] = m_RGB[2] * 255;

	cgi_R_AddPolyToScene( m_shader, 3, verts );

	VectorCopy( m_origin, verts[0].xyz );
	verts[0].st[0] = 0.5f;
	verts[0].st[1] = 0.0f;

	VectorMA( m_origin2, -scale2, cross, verts[1].xyz );
	verts[1].st[0] = 0.0f;
	verts[1].st[1] = m_stScale;

	VectorMA( m_origin, -scale, cross, verts[2].xyz );
	verts[2].st[0] = 0.0f;
	verts[2].st[1] = m_stScale;

	cgi_R_AddPolyToScene( m_shader, 3, verts );

	VectorCopy( m_origin, verts[0].xyz );
	verts[0].st[0] = 0.5f;
	verts[0].st[1] = 0.0f;

	VectorMA( m_origin2, scale2, cross, verts[1].xyz );
	verts[1].st[0] = 0.0f;
	verts[1].st[1] = m_stScale;

	VectorMA( m_origin, scale, cross, verts[2].xyz );
	verts[2].st[0] = 0.0f;
	verts[2].st[1] = m_stScale;

	cgi_R_AddPolyToScene( m_shader, 3, verts );
/*
	VectorMA( m_origin, scale, cross, verts[1].xyz );
	verts[1].st[0] = 1.0f;
	verts[1].st[1] = 0.0f;
	verts[1].modulate[0] = m_RGB[0] * 255;
	verts[1].modulate[1] = m_RGB[1] * 255;
	verts[1].modulate[2] = m_RGB[2] * 255;

	VectorMA( m_origin2, scale2, cross, verts[2].xyz );
	verts[2].st[0] = 1.0f;
	verts[2].st[1] = m_stScale;
	verts[2].modulate[0] = m_RGB[0] * 255;
	verts[2].modulate[1] = m_RGB[1] * 255;
	verts[2].modulate[2] = m_RGB[2] * 255;

	VectorMA( m_origin2, -scale2, cross, verts[3].xyz );
	verts[3].st[0] = 0.0f;
	verts[3].st[1] = m_stScale;
	verts[3].modulate[0] = m_RGB[0] * 255;
	verts[3].modulate[1] = m_RGB[1] * 255;
	verts[3].modulate[2] = m_RGB[2] * 255;

	cgi_R_AddPolyToScene( m_shader, 4, verts );
	*/
#endif
}