Esempio n. 1
0
void DrawSkyPolygon (int nump, vec3_t vecs)
{
	int		i,j;
	vec3_t	v, av;
	float	s, t, dv;
	int		axis;
	float	*vp;

	c_sky++;
#if 0
glBegin (GL_POLYGON);
for (i=0 ; i<nump ; i++, vecs+=3)
{
	VectorAdd(vecs, r_origin, v);
	qglVertex3fv (v);
}
glEnd();
return;
#endif
	// decide which face it maps to
	VectorCopy (vec3_origin, v);
	for (i=0, vp=vecs ; i<nump ; i++, vp+=3)
	{
		VectorAdd (vp, v, v);
	}
	av[0] = fabs(v[0]);
	av[1] = fabs(v[1]);
	av[2] = fabs(v[2]);
	if (av[0] > av[1] && av[0] > av[2])
	{
		if (v[0] < 0)
			axis = 1;
		else
			axis = 0;
	}
	else if (av[1] > av[2] && av[1] > av[0])
	{
		if (v[1] < 0)
			axis = 3;
		else
			axis = 2;
	}
	else
	{
		if (v[2] < 0)
			axis = 5;
		else
			axis = 4;
	}

	// project new texture coords
	for (i=0 ; i<nump ; i++, vecs+=3)
	{
		j = vec_to_st[axis][2];
		if (j > 0)
			dv = vecs[j - 1];
		else
			dv = -vecs[-j - 1];
		if (dv < 0.001)
			continue;	// don't divide by zero
		j = vec_to_st[axis][0];
		if (j < 0)
			s = -vecs[-j -1] / dv;
		else
			s = vecs[j-1] / dv;
		j = vec_to_st[axis][1];
		if (j < 0)
			t = -vecs[-j -1] / dv;
		else
			t = vecs[j-1] / dv;

		if (s < skymins[0][axis])
			skymins[0][axis] = s;
		if (t < skymins[1][axis])
			skymins[1][axis] = t;
		if (s > skymaxs[0][axis])
			skymaxs[0][axis] = s;
		if (t > skymaxs[1][axis])
			skymaxs[1][axis] = t;
	}
}
Esempio n. 2
0
void R_RenderShadowEdges( void ) {
	int		i;

#if 0
	int		numTris;

	// dumb way -- render every triangle's edges
	numTris = tess.numIndexes / 3;

	for ( i = 0 ; i < numTris ; i++ ) {
		int		i1, i2, i3;

		if ( !facing[i] ) {
			continue;
		}

		i1 = tess.indexes[ i*3 + 0 ];
		i2 = tess.indexes[ i*3 + 1 ];
		i3 = tess.indexes[ i*3 + 2 ];

		qglBegin( GL_TRIANGLE_STRIP );
		qglVertex3fv( tess.xyz[ i1 ] );
		qglVertex3fv( tess.xyz[ i1 + tess.numVertexes ] );
		qglVertex3fv( tess.xyz[ i2 ] );
		qglVertex3fv( tess.xyz[ i2 + tess.numVertexes ] );
		qglVertex3fv( tess.xyz[ i3 ] );
		qglVertex3fv( tess.xyz[ i3 + tess.numVertexes ] );
		qglVertex3fv( tess.xyz[ i1 ] );
		qglVertex3fv( tess.xyz[ i1 + tess.numVertexes ] );
		qglEnd();
	}
#else
	int		c, c2;
	int		j, k;
	int		i2;
	int		c_edges, c_rejected;
	int		hit[2];
	#ifdef HAVE_GLES
	idx = 0;
	#endif

	// an edge is NOT a silhouette edge if its face doesn't face the light,
	// or if it has a reverse paired edge that also faces the light.
	// A well behaved polyhedron would have exactly two faces for each edge,
	// but lots of models have dangling edges or overfanned edges
	c_edges = 0;
	c_rejected = 0;

	for ( i = 0 ; i < tess.numVertexes ; i++ ) {
		c = numEdgeDefs[ i ];
		for ( j = 0 ; j < c ; j++ ) {
			if ( !edgeDefs[ i ][ j ].facing ) {
				continue;
			}

			hit[0] = 0;
			hit[1] = 0;

			i2 = edgeDefs[ i ][ j ].i2;
			c2 = numEdgeDefs[ i2 ];
			for ( k = 0 ; k < c2 ; k++ ) {
				if ( edgeDefs[ i2 ][ k ].i2 == i ) {
					hit[ edgeDefs[ i2 ][ k ].facing ]++;
				}
			}

			// if it doesn't share the edge with another front facing
			// triangle, it is a sil edge
			if ( hit[ 1 ] == 0 ) {
				#ifdef HAVE_GLES
				// A single drawing call is better than many. So I prefer a singe TRIANGLES call than many TRAINGLE_STRIP call
				// even if it seems less efficiant, it's faster on the PANDORA
				indexes[idx++] = i;
				indexes[idx++] = i + tess.numVertexes;
				indexes[idx++] = i2;
				indexes[idx++] = i2;
				indexes[idx++] = i + tess.numVertexes;
				indexes[idx++] = i2 + tess.numVertexes;
				#else
				qglBegin( GL_TRIANGLE_STRIP );
				qglVertex3fv( tess.xyz[ i ] );
				qglVertex3fv( tess.xyz[ i + tess.numVertexes ] );
				qglVertex3fv( tess.xyz[ i2 ] );
				qglVertex3fv( tess.xyz[ i2 + tess.numVertexes ] );
				qglEnd();
				#endif
				c_edges++;
			} else {
				c_rejected++;
			}
		}
	}
	#ifdef HAVE_GLES
	qglDrawElements(GL_TRIANGLES, idx, GL_UNSIGNED_SHORT, indexes);
	#endif

#endif
}
Esempio n. 3
0
/*
=============
GL_DrawAliasFrameLerp

interpolates between two frames and origins
FIXME: batch lerp all vertexes
=============
*/
void GL_DrawAliasFrameLerp (dmdl_t *paliashdr, float backlerp)
{
	float 	l;
	daliasframe_t	*frame, *oldframe;
	dtrivertx_t	*v, *ov, *verts;
	int		*order;
	int		count;
	float	frontlerp;
	float	alpha;
	vec3_t	move, delta, vectors[3];
	vec3_t	frontv, backv;
	int		i;
	int		index_xyz;
	float	*lerp;

	frame = (daliasframe_t *)((byte *)paliashdr + paliashdr->ofs_frames 
		+ currententity->frame * paliashdr->framesize);
	verts = v = frame->verts;

	oldframe = (daliasframe_t *)((byte *)paliashdr + paliashdr->ofs_frames 
		+ currententity->oldframe * paliashdr->framesize);
	ov = oldframe->verts;

	order = (int *)((byte *)paliashdr + paliashdr->ofs_glcmds);

//	glTranslatef (frame->translate[0], frame->translate[1], frame->translate[2]);
//	glScalef (frame->scale[0], frame->scale[1], frame->scale[2]);

	if (currententity->flags & RF_TRANSLUCENT)
		alpha = currententity->alpha;
	else
		alpha = 1.0;

	// PMM - added double shell
	if ( currententity->flags & ( RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE | RF_SHELL_DOUBLE | RF_SHELL_HALF_DAM) )
		qglDisable( GL_TEXTURE_2D );

	frontlerp = 1.0 - backlerp;

	// move should be the delta back to the previous frame * backlerp
	VectorSubtract (currententity->oldorigin, currententity->origin, delta);
	AngleVectors (currententity->angles, vectors[0], vectors[1], vectors[2]);

	move[0] = DotProduct (delta, vectors[0]);	// forward
	move[1] = -DotProduct (delta, vectors[1]);	// left
	move[2] = DotProduct (delta, vectors[2]);	// up

	VectorAdd (move, oldframe->translate, move);

	for (i=0 ; i<3 ; i++)
	{
		move[i] = backlerp*move[i] + frontlerp*frame->translate[i];
	}

	for (i=0 ; i<3 ; i++)
	{
		frontv[i] = frontlerp*frame->scale[i];
		backv[i] = backlerp*oldframe->scale[i];
	}

	lerp = s_lerped[0];

	GL_LerpVerts( paliashdr->num_xyz, v, ov, verts, lerp, move, frontv, backv );

	if ( gl_vertex_arrays->value )
	{
		float colorArray[MAX_VERTS*4];

		qglEnableClientState( GL_VERTEX_ARRAY );
		qglVertexPointer( 3, GL_FLOAT, 16, s_lerped );	// padded for SIMD

//		if ( currententity->flags & ( RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE ) )
		// PMM - added double damage shell
		if ( currententity->flags & ( RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE | RF_SHELL_DOUBLE | RF_SHELL_HALF_DAM) )
		{
			qglColor4f( shadelight[0], shadelight[1], shadelight[2], alpha );
		}
		else
		{
			qglEnableClientState( GL_COLOR_ARRAY );
			qglColorPointer( 3, GL_FLOAT, 0, colorArray );

			//
			// pre light everything
			//
			for ( i = 0; i < paliashdr->num_xyz; i++ )
			{
				float l = shadedots[verts[i].lightnormalindex];

				colorArray[i*3+0] = l * shadelight[0];
				colorArray[i*3+1] = l * shadelight[1];
				colorArray[i*3+2] = l * shadelight[2];
			}
		}

		if ( qglLockArraysEXT != 0 )
			qglLockArraysEXT( 0, paliashdr->num_xyz );

		while (1)
		{
			// get the vertex count and primitive type
			count = *order++;
			if (!count)
				break;		// done
			if (count < 0)
			{
				count = -count;
				qglBegin (GL_TRIANGLE_FAN);
			}
			else
			{
				qglBegin (GL_TRIANGLE_STRIP);
			}

			// PMM - added double damage shell
			if ( currententity->flags & ( RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE | RF_SHELL_DOUBLE | RF_SHELL_HALF_DAM) )
			{
				do
				{
					index_xyz = order[2];
					order += 3;

					qglVertex3fv( s_lerped[index_xyz] );

				} while (--count);
			}
			else
			{
				do
				{
					// texture coordinates come from the draw list
					qglTexCoord2f (((float *)order)[0], ((float *)order)[1]);
					index_xyz = order[2];

					order += 3;

					// normals and vertexes come from the frame list
//					l = shadedots[verts[index_xyz].lightnormalindex];
					
//					qglColor4f (l* shadelight[0], l*shadelight[1], l*shadelight[2], alpha);
					qglArrayElement( index_xyz );

				} while (--count);
			}
			qglEnd ();
		}

		if ( qglUnlockArraysEXT != 0 )
			qglUnlockArraysEXT();
	}
	else
	{
		while (1)
		{
			// get the vertex count and primitive type
			count = *order++;
			if (!count)
				break;		// done
			if (count < 0)
			{
				count = -count;
				qglBegin (GL_TRIANGLE_FAN);
			}
			else
			{
				qglBegin (GL_TRIANGLE_STRIP);
			}

			if ( currententity->flags & ( RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE ) )
			{
				do
				{
					index_xyz = order[2];
					order += 3;

					qglColor4f( shadelight[0], shadelight[1], shadelight[2], alpha);
					qglVertex3fv (s_lerped[index_xyz]);

				} while (--count);
			}
			else
			{
				do
				{
					// texture coordinates come from the draw list
					qglTexCoord2f (((float *)order)[0], ((float *)order)[1]);
					index_xyz = order[2];
					order += 3;

					// normals and vertexes come from the frame list
					l = shadedots[verts[index_xyz].lightnormalindex];
					
					qglColor4f (l* shadelight[0], l*shadelight[1], l*shadelight[2], alpha);
					qglVertex3fv (s_lerped[index_xyz]);
				} while (--count);
			}

			qglEnd ();
		}
	}

//	if ( currententity->flags & ( RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE ) )
	// PMM - added double damage shell
	if ( currententity->flags & ( RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE | RF_SHELL_DOUBLE | RF_SHELL_HALF_DAM) )
		qglEnable( GL_TEXTURE_2D );
}
Esempio n. 4
0
static void DrawSkySide( struct image_s *image, const int mins[2], const int maxs[2] )
{
	int s, t;

	GL_Bind( image );
	#ifdef HAVE_GLES
	GLfloat vtx[3*1024];	// arbitrary sized
	GLfloat tex[2*1024];
	int idx;

	GLboolean text = qglIsEnabled(GL_TEXTURE_COORD_ARRAY);
	GLboolean glcol = qglIsEnabled(GL_COLOR_ARRAY);
	if (glcol)
		qglDisableClientState(GL_COLOR_ARRAY);
	if (!text)
		qglEnableClientState( GL_TEXTURE_COORD_ARRAY );
	#endif

#ifdef _XBOX
	int verts = ((maxs[0]+HALF_SKY_SUBDIVISIONS) - (mins[0]+HALF_SKY_SUBDIVISIONS)) * 2 + 2;
#endif

	for ( t = mins[1]+HALF_SKY_SUBDIVISIONS; t < maxs[1]+HALF_SKY_SUBDIVISIONS; t++ )
	{
#ifdef _XBOX
		qglBeginEXT( GL_TRIANGLE_STRIP, verts, 0, 0, verts, 0);
#else
#ifdef HAVE_GLES
		idx=0;
#else
		qglBegin( GL_TRIANGLE_STRIP );
#endif
#endif

		for ( s = mins[0]+HALF_SKY_SUBDIVISIONS; s <= maxs[0]+HALF_SKY_SUBDIVISIONS; s++ )
		{
			#ifdef HAVE_GLES
			memcpy(tex+idx*2, s_skyTexCoords[t][s], sizeof(GLfloat)*2);
			memcpy(vtx+idx*3, s_skyPoints[t][s], sizeof(GLfloat)*3);
			idx++;
			memcpy(tex+idx*2, s_skyTexCoords[t+1][s], sizeof(GLfloat)*2);
			memcpy(vtx+idx*3, s_skyPoints[t+1][s], sizeof(GLfloat)*3);
			idx++;
			#else
			qglTexCoord2fv( s_skyTexCoords[t][s] );
			qglVertex3fv( s_skyPoints[t][s] );

			qglTexCoord2fv( s_skyTexCoords[t+1][s] );
			qglVertex3fv( s_skyPoints[t+1][s] );
			#endif
		}

		#ifdef HAVE_GLES

		qglVertexPointer (3, GL_FLOAT, 0, vtx);
		qglTexCoordPointer(2, GL_FLOAT, 0, tex);
		qglDrawArrays(GL_TRIANGLE_STRIP, 0, idx);
		#else
		qglEnd();
		#endif
	}
	#ifdef HAVE_GLES
	if (glcol)
		qglEnableClientState(GL_COLOR_ARRAY);
	if (!text)
		qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
	#endif
}
void CWind::Render(CWorldEffectsSystem *system)
{
	vec3_t	output;

	if (!mEnabled || !debugShowWind)
	{
		return;
	}

	qglDisable(GL_TEXTURE_2D);
	qglDisable(GL_CULL_FACE);
	GL_State(GLS_ALPHA);

	qglColor4f(1.0, 0.0, 0.0, 0.5);
	qglBegin(GL_QUADS);
	
	VectorMA(mPoint, -(mSize[0]/2.0), mPlanes[0], output);
	VectorMA(output, -(mSize[1]/2.0), mPlanes[1], output);
	VectorMA(output, -(mSize[2]/2.0), mPlanes[2], output);
	qglVertex3fv(output);

	VectorMA(mPoint, -(mSize[0]/2.0), mPlanes[0], output);
	VectorMA(output, (mSize[1]/2.0), mPlanes[1], output);
	VectorMA(output, -(mSize[2]/2.0), mPlanes[2], output);
	qglVertex3fv(output);

	VectorMA(mPoint, -(mSize[0]/2.0), mPlanes[0], output);
	VectorMA(output, (mSize[1]/2.0), mPlanes[1], output);
	VectorMA(output, (mSize[2]/2.0), mPlanes[2], output);
	qglVertex3fv(output);

	VectorMA(mPoint, -(mSize[0]/2.0), mPlanes[0], output);
	VectorMA(output, -(mSize[1]/2.0), mPlanes[1], output);
	VectorMA(output, (mSize[2]/2.0), mPlanes[2], output);
	qglVertex3fv(output);

	
	
	qglColor4f(0.0, 1.0, 0.0, 0.5);
	VectorMA(mPoint, -(mSize[0]/2.0), mPlanes[0], output);
	VectorMA(output, -(mSize[1]/2.0), mPlanes[1], output);
	VectorMA(output, -(mSize[2]/2.0), mPlanes[2], output);
	qglVertex3fv(output);

	VectorMA(mPoint, (mSize[0]/2.0), mPlanes[0], output);
	VectorMA(output, -(mSize[1]/2.0), mPlanes[1], output);
	VectorMA(output, -(mSize[2]/2.0), mPlanes[2], output);
	qglVertex3fv(output);

	VectorMA(mPoint, (mSize[0]/2.0), mPlanes[0], output);
	VectorMA(output, -(mSize[1]/2.0), mPlanes[1], output);
	VectorMA(output, (mSize[2]/2.0), mPlanes[2], output);
	qglVertex3fv(output);

	VectorMA(mPoint, -(mSize[0]/2.0), mPlanes[0], output);
	VectorMA(output, -(mSize[1]/2.0), mPlanes[1], output);
	VectorMA(output, (mSize[2]/2.0), mPlanes[2], output);
	qglVertex3fv(output);
	

	qglColor4f(0.0, 0.0, 1.0, 0.5);
	VectorMA(mPoint, -(mSize[0]/2.0), mPlanes[0], output);
	VectorMA(output, -(mSize[2]/2.0), mPlanes[2], output);
	VectorMA(output, -(mSize[1]/2.0), mPlanes[1], output);
	qglVertex3fv(output);

	VectorMA(mPoint, (mSize[0]/2.0), mPlanes[0], output);
	VectorMA(output, -(mSize[2]/2.0), mPlanes[2], output);
	VectorMA(output, -(mSize[1]/2.0), mPlanes[1], output);
	qglVertex3fv(output);

	VectorMA(mPoint, (mSize[0]/2.0), mPlanes[0], output);
	VectorMA(output, -(mSize[2]/2.0), mPlanes[2], output);
	VectorMA(output, (mSize[1]/2.0), mPlanes[1], output);
	qglVertex3fv(output);

	VectorMA(mPoint, -(mSize[0]/2.0), mPlanes[0], output);
	VectorMA(output, -(mSize[2]/2.0), mPlanes[2], output);
	VectorMA(output, (mSize[1]/2.0), mPlanes[1], output);
	qglVertex3fv(output);
	
	
	qglEnd();

	qglEnable(GL_CULL_FACE);
	qglEnable(GL_TEXTURE_2D);
}
Esempio n. 6
0
/*
=================
R_DrawAliasModel

=================
*/
void R_DrawAliasModel (entity_t *e)
{
	int			i;
	dmdl_t		*paliashdr;
	float		an;
	vec3_t		bbox[8];
	image_t		*skin;

	if ( !( e->flags & RF_WEAPONMODEL ) )
	{
		if ( R_CullAliasModel( bbox, e ) )
			return;
	}

	if ( e->flags & RF_WEAPONMODEL )
	{
		if ( r_lefthand->value == 2 )
			return;
	}

	paliashdr = (dmdl_t *)currentmodel->extradata;

	//
	// get lighting information
	//
	// PMM - rewrote, reordered to handle new shells & mixing
	// PMM - 3.20 code .. replaced with original way of doing it to keep mod authors happy
	//
	if ( currententity->flags & ( RF_SHELL_HALF_DAM | RF_SHELL_GREEN | RF_SHELL_RED | RF_SHELL_BLUE | RF_SHELL_DOUBLE ) )
	{
		VectorClear (shadelight);
		if (currententity->flags & RF_SHELL_HALF_DAM)
		{
				shadelight[0] = 0.56;
				shadelight[1] = 0.59;
				shadelight[2] = 0.45;
		}
		if ( currententity->flags & RF_SHELL_DOUBLE )
		{
			shadelight[0] = 0.9;
			shadelight[1] = 0.7;
		}
		if ( currententity->flags & RF_SHELL_RED )
			shadelight[0] = 1.0;
		if ( currententity->flags & RF_SHELL_GREEN )
			shadelight[1] = 1.0;
		if ( currententity->flags & RF_SHELL_BLUE )
			shadelight[2] = 1.0;
	}
/*
		// PMM -special case for godmode
		if ( (currententity->flags & RF_SHELL_RED) &&
			(currententity->flags & RF_SHELL_BLUE) &&
			(currententity->flags & RF_SHELL_GREEN) )
		{
			for (i=0 ; i<3 ; i++)
				shadelight[i] = 1.0;
		}
		else if ( currententity->flags & ( RF_SHELL_RED | RF_SHELL_BLUE | RF_SHELL_DOUBLE ) )
		{
			VectorClear (shadelight);

			if ( currententity->flags & RF_SHELL_RED )
			{
				shadelight[0] = 1.0;
				if (currententity->flags & (RF_SHELL_BLUE|RF_SHELL_DOUBLE) )
					shadelight[2] = 1.0;
			}
			else if ( currententity->flags & RF_SHELL_BLUE )
			{
				if ( currententity->flags & RF_SHELL_DOUBLE )
				{
					shadelight[1] = 1.0;
					shadelight[2] = 1.0;
				}
				else
				{
					shadelight[2] = 1.0;
				}
			}
			else if ( currententity->flags & RF_SHELL_DOUBLE )
			{
				shadelight[0] = 0.9;
				shadelight[1] = 0.7;
			}
		}
		else if ( currententity->flags & ( RF_SHELL_HALF_DAM | RF_SHELL_GREEN ) )
		{
			VectorClear (shadelight);
			// PMM - new colors
			if ( currententity->flags & RF_SHELL_HALF_DAM )
			{
				shadelight[0] = 0.56;
				shadelight[1] = 0.59;
				shadelight[2] = 0.45;
			}
			if ( currententity->flags & RF_SHELL_GREEN )
			{
				shadelight[1] = 1.0;
			}
		}
	}
			//PMM - ok, now flatten these down to range from 0 to 1.0.
	//		max_shell_val = max(shadelight[0], max(shadelight[1], shadelight[2]));
	//		if (max_shell_val > 0)
	//		{
	//			for (i=0; i<3; i++)
	//			{
	//				shadelight[i] = shadelight[i] / max_shell_val;
	//			}
	//		}
	// pmm
*/
	else if ( currententity->flags & RF_FULLBRIGHT )
	{
		for (i=0 ; i<3 ; i++)
			shadelight[i] = 1.0;
	}
	else
	{
		R_LightPoint (currententity->origin, shadelight);

		// player lighting hack for communication back to server
		// big hack!
		if ( currententity->flags & RF_WEAPONMODEL )
		{
			// pick the greatest component, which should be the same
			// as the mono value returned by software
			if (shadelight[0] > shadelight[1])
			{
				if (shadelight[0] > shadelight[2])
					r_lightlevel->value = 150*shadelight[0];
				else
					r_lightlevel->value = 150*shadelight[2];
			}
			else
			{
				if (shadelight[1] > shadelight[2])
					r_lightlevel->value = 150*shadelight[1];
				else
					r_lightlevel->value = 150*shadelight[2];
			}

		}
		
		if ( gl_monolightmap->string[0] != '0' )
		{
			float s = shadelight[0];

			if ( s < shadelight[1] )
				s = shadelight[1];
			if ( s < shadelight[2] )
				s = shadelight[2];

			shadelight[0] = s;
			shadelight[1] = s;
			shadelight[2] = s;
		}
	}

	if ( currententity->flags & RF_MINLIGHT )
	{
		for (i=0 ; i<3 ; i++)
			if (shadelight[i] > 0.1)
				break;
		if (i == 3)
		{
			shadelight[0] = 0.1;
			shadelight[1] = 0.1;
			shadelight[2] = 0.1;
		}
	}

	if ( currententity->flags & RF_GLOW )
	{	// bonus items will pulse with time
		float	scale;
		float	min;

		scale = 0.1 * sin(r_newrefdef.time*7);
		for (i=0 ; i<3 ; i++)
		{
			min = shadelight[i] * 0.8;
			shadelight[i] += scale;
			if (shadelight[i] < min)
				shadelight[i] = min;
		}
	}

// =================
// PGM	ir goggles color override
	if ( r_newrefdef.rdflags & RDF_IRGOGGLES && currententity->flags & RF_IR_VISIBLE)
	{
		shadelight[0] = 1.0;
		shadelight[1] = 0.0;
		shadelight[2] = 0.0;
	}
// PGM	
// =================

	shadedots = r_avertexnormal_dots[((int)(currententity->angles[1] * (SHADEDOT_QUANT / 360.0))) & (SHADEDOT_QUANT - 1)];
	
	an = currententity->angles[1]/180*M_PI;
	shadevector[0] = cos(-an);
	shadevector[1] = sin(-an);
	shadevector[2] = 1;
	VectorNormalize (shadevector);

	//
	// locate the proper data
	//

	c_alias_polys += paliashdr->num_tris;

	//
	// draw all the triangles
	//
	if (currententity->flags & RF_DEPTHHACK) // hack the depth range to prevent view model from poking into walls
		qglDepthRange (gldepthmin, gldepthmin + 0.3*(gldepthmax-gldepthmin));

	if ( ( currententity->flags & RF_WEAPONMODEL ) && ( r_lefthand->value == 1.0F ) )
	{
		extern void MYgluPerspective( GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar );

		qglMatrixMode( GL_PROJECTION );
		qglPushMatrix();
		qglLoadIdentity();
		qglScalef( -1, 1, 1 );

		// jkrige - increased far plane
	    MYgluPerspective( r_newrefdef.fov_y, ( float ) r_newrefdef.width / r_newrefdef.height,  4,  6144);
		//MYgluPerspective( r_newrefdef.fov_y, ( float ) r_newrefdef.width / r_newrefdef.height,  4,  4096);
		// jkrige - increased far plane

		qglMatrixMode( GL_MODELVIEW );

		qglCullFace( GL_BACK );
	}

    qglPushMatrix ();
	e->angles[PITCH] = -e->angles[PITCH];	// sigh.
	R_RotateForEntity (e);
	e->angles[PITCH] = -e->angles[PITCH];	// sigh.

	// select skin
	if (currententity->skin)
		skin = currententity->skin;	// custom player skin
	else
	{
		if (currententity->skinnum >= MAX_MD2SKINS)
			skin = currentmodel->skins[0];
		else
		{
			skin = currentmodel->skins[currententity->skinnum];
			if (!skin)
				skin = currentmodel->skins[0];
		}
	}
	if (!skin)
		skin = r_notexture;	// fallback...
	GL_Bind(skin->texnum);

	// draw it

	qglShadeModel (GL_SMOOTH);

	GL_TexEnv( GL_MODULATE );
	if ( currententity->flags & RF_TRANSLUCENT )
	{
		qglEnable (GL_BLEND);
	}


	if ( (currententity->frame >= paliashdr->num_frames) 
		|| (currententity->frame < 0) )
	{
		ri.Con_Printf (PRINT_ALL, "R_DrawAliasModel %s: no such frame %d\n",
			currentmodel->name, currententity->frame);
		currententity->frame = 0;
		currententity->oldframe = 0;
	}

	if ( (currententity->oldframe >= paliashdr->num_frames)
		|| (currententity->oldframe < 0))
	{
		ri.Con_Printf (PRINT_ALL, "R_DrawAliasModel %s: no such oldframe %d\n",
			currentmodel->name, currententity->oldframe);
		currententity->frame = 0;
		currententity->oldframe = 0;
	}

	if ( !r_lerpmodels->value )
		currententity->backlerp = 0;
	GL_DrawAliasFrameLerp (paliashdr, currententity->backlerp);

	GL_TexEnv( GL_REPLACE );
	qglShadeModel (GL_FLAT);

	qglPopMatrix ();

#if 0
	qglDisable( GL_CULL_FACE );
	qglPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
	qglDisable( GL_TEXTURE_2D );
	qglBegin( GL_TRIANGLE_STRIP );
	for ( i = 0; i < 8; i++ )
	{
		qglVertex3fv( bbox[i] );
	}
	qglEnd();
	qglEnable( GL_TEXTURE_2D );
	qglPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
	qglEnable( GL_CULL_FACE );
#endif

	if ( ( currententity->flags & RF_WEAPONMODEL ) && ( r_lefthand->value == 1.0F ) )
	{
		qglMatrixMode( GL_PROJECTION );
		qglPopMatrix();
		qglMatrixMode( GL_MODELVIEW );
		qglCullFace( GL_FRONT );
	}

	if ( currententity->flags & RF_TRANSLUCENT )
	{
		qglDisable (GL_BLEND);
	}

	if (currententity->flags & RF_DEPTHHACK)
		qglDepthRange (gldepthmin, gldepthmax);

// jkrige - removed alias shadows
#if 0
	if (gl_shadows->value && !(currententity->flags & (RF_TRANSLUCENT | RF_WEAPONMODEL)))
	{
		qglPushMatrix ();
		R_RotateForEntity (e);
		qglDisable (GL_TEXTURE_2D);
		qglEnable (GL_BLEND);
		qglColor4f (0,0,0,0.5);
		GL_DrawAliasShadow (paliashdr, currententity->frame );
		qglEnable (GL_TEXTURE_2D);
		qglDisable (GL_BLEND);
		qglPopMatrix ();
	}
#endif
// jkrige - removed alias shadows

	qglColor4f (1,1,1,1);
}
Esempio n. 7
0
/*
===============
CreateOptTri
===============
*/
static void CreateOptTri( optVertex_t *first, optEdge_t *e1, optEdge_t *e2, optIsland_t *island ) {
	optEdge_t		*opposite;
	optVertex_t		*second, *third;
	optTri_t		*optTri;
	mapTri_t		*tri;

	if ( e1->v1 == first ) {
		second = e1->v2;
	} else if ( e1->v2 == first ) {
		second = e1->v1;
	} else {
		common->Error( "CreateOptTri: mislinked edge" );
		return;
	}

	if ( e2->v1 == first ) {
		third = e2->v2;
	} else if ( e2->v2 == first ) {
		third = e2->v1;
	} else {
		common->Error( "CreateOptTri: mislinked edge" );
		return;
	}

	if ( !IsTriangleValid( first, second, third ) ) {
		common->Error( "CreateOptTri: invalid" );
		return;
	}

//DrawEdges( island );

		// identify the third edge
	if ( dmapGlobals.drawflag ) {
		qglColor3f(1,1,0);
		qglBegin( GL_LINES );
		qglVertex3fv( e1->v1->pv.ToFloatPtr() );
		qglVertex3fv( e1->v2->pv.ToFloatPtr() );
		qglEnd();
		qglFlush();
		qglColor3f(0,1,1);
		qglBegin( GL_LINES );
		qglVertex3fv( e2->v1->pv.ToFloatPtr() );
		qglVertex3fv( e2->v2->pv.ToFloatPtr() );
		qglEnd();
		qglFlush();
	}

	for ( opposite = second->edges ; opposite ; ) {
		if ( opposite != e1 && ( opposite->v1 == third || opposite->v2 == third ) ) {
			break;
		}
		if ( opposite->v1 == second ) {
			opposite = opposite->v1link;
		} else if ( opposite->v2 == second ) {
			opposite = opposite->v2link;
		} else {
			common->Error( "BuildOptTriangles: mislinked edge" );
			return;
		}
	}

	if ( !opposite ) {
		common->Printf( "Warning: BuildOptTriangles: couldn't locate opposite\n" );
		return;
	}

	if ( dmapGlobals.drawflag ) {
		qglColor3f(1,0,1);
		qglBegin( GL_LINES );
		qglVertex3fv( opposite->v1->pv.ToFloatPtr() );
		qglVertex3fv( opposite->v2->pv.ToFloatPtr() );
		qglEnd();
		qglFlush();
	}

	// create new triangle
	optTri = (optTri_t *)Mem_Alloc( sizeof( *optTri ) );
	optTri->v[0] = first;
	optTri->v[1] = second;
	optTri->v[2] = third;
	optTri->midpoint = ( optTri->v[0]->pv + optTri->v[1]->pv + optTri->v[2]->pv ) * ( 1.0f / 3.0f );
	optTri->next = island->tris;
	island->tris = optTri;

	if ( dmapGlobals.drawflag ) {
		qglColor3f( 1, 1, 1 );
		qglPointSize( 4 );
		qglBegin( GL_POINTS );
		qglVertex3fv( optTri->midpoint.ToFloatPtr() );
		qglEnd();
		qglFlush();
	}

	// find the midpoint, and scan through all the original triangles to
	// see if it is inside any of them
	for ( tri = island->group->triList ; tri ; tri = tri->next ) {
		if ( PointInTri( optTri->midpoint, tri, island ) ) {
			break;
		}
	}
	if ( tri ) {
		optTri->filled = true;
	} else {
		optTri->filled = false;
	}
	if ( dmapGlobals.drawflag ) {
		if ( optTri->filled ) {
			qglColor3f( ( 128 + orandom.RandomInt( 127 ) )/ 255.0, 0, 0 );
		} else {
			qglColor3f( 0, ( 128 + orandom.RandomInt( 127 ) ) / 255.0, 0 );
		}
		qglBegin( GL_TRIANGLES );
		qglVertex3fv( optTri->v[0]->pv.ToFloatPtr() );
		qglVertex3fv( optTri->v[1]->pv.ToFloatPtr() );
		qglVertex3fv( optTri->v[2]->pv.ToFloatPtr() );
		qglEnd();
		qglColor3f( 1, 1, 1 );
		qglBegin( GL_LINE_LOOP );
		qglVertex3fv( optTri->v[0]->pv.ToFloatPtr() );
		qglVertex3fv( optTri->v[1]->pv.ToFloatPtr() );
		qglVertex3fv( optTri->v[2]->pv.ToFloatPtr() );
		qglEnd();
		qglFlush();
	}

	// link the triangle to it's edges
	LinkTriToEdge( optTri, e1 );
	LinkTriToEdge( optTri, e2 );
	LinkTriToEdge( optTri, opposite );
}
/*
====================
BuildOptTriangles

Generate a new list of triangles from the optEdeges
====================
*/
static void BuildOptTriangles( optIsland_t *island ) {
	optVertex_t		*ov, *second, *third, *middle;
	optEdge_t		*e1, *e1Next, *e2, *e2Next, *check, *checkNext;

	// free them
	FreeOptTriangles( island );

	// clear the vertex emitted flags
	for ( ov = island->verts ; ov ; ov = ov->islandLink ) {
		ov->emited = false;
	}

	// clear the edge triangle links
	for ( check = island->edges ; check ; check = check->islandLink ) {
		check->frontTri = check->backTri = NULL;
	}

	// check all possible triangle made up out of the
	// edges coming off the vertex
	for ( ov = island->verts ; ov ; ov = ov->islandLink ) {
		if ( !ov->edges ) {
			continue;
		}

#if 0
if ( dmapGlobals.drawflag && ov == (optVertex_t *)0x1845a60 ) {
for ( e1 = ov->edges ; e1 ; e1 = e1Next ) {
	qglBegin( GL_LINES );
	qglColor3f( 0,1,0 );
	qglVertex3fv( e1->v1->pv.ToFloatPtr() );
	qglVertex3fv( e1->v2->pv.ToFloatPtr() );
	qglEnd();
	qglFlush();
	if ( e1->v1 == ov ) {
		e1Next = e1->v1link;
	} else if ( e1->v2 == ov ) {
		e1Next = e1->v2link;
	}
}
}
#endif
		for ( e1 = ov->edges ; e1 ; e1 = e1Next ) {
			if ( e1->v1 == ov ) {
				second = e1->v2;
				e1Next = e1->v1link;
			} else if ( e1->v2 == ov ) {
				second = e1->v1;
				e1Next = e1->v2link;
			} else {
				common->Error( "BuildOptTriangles: mislinked edge" );
			}

			// if the vertex has already been used, it can't be used again
			if ( second->emited ) {
				continue;
			}

			for ( e2 = ov->edges ; e2 ; e2 = e2Next ) {
				if ( e2->v1 == ov ) {
					third = e2->v2;
					e2Next = e2->v1link;
				} else if ( e2->v2 == ov ) {
					third = e2->v1;
					e2Next = e2->v2link;
				} else {
					common->Error( "BuildOptTriangles: mislinked edge" );
				}
				if ( e2 == e1 ) {
					continue;
				}

				// if the vertex has already been used, it can't be used again
				if ( third->emited ) {
					continue;
				}

				// if the triangle is backwards or degenerate, don't use it
				if ( !IsTriangleValid( ov, second, third ) ) {
					continue;
				}

				// see if any other edge bisects these two, which means
				// this triangle shouldn't be used
				for ( check = ov->edges ; check ; check = checkNext ) {
					if ( check->v1 == ov ) {
						middle = check->v2;
						checkNext = check->v1link;
					} else if ( check->v2 == ov ) {
						middle = check->v1;
						checkNext = check->v2link;
					} else {
						common->Error( "BuildOptTriangles: mislinked edge" );
					}

					if ( check == e1 || check == e2 ) {
						continue;
					}

					if ( IsTriangleValid( ov, second, middle ) 
						&& IsTriangleValid( ov, middle, third ) ) {
						break;	// should use the subdivided ones
					}
				}

				if ( check ) {
					continue;	// don't use it
				}

				// the triangle is valid
				CreateOptTri( ov, e1, e2, island );
			}
		}

		// later vertexes will not emit triangles that use an
		// edge that this vert has already used
		ov->emited = true;
	}
}
Esempio n. 9
0
/*
==============
R_CalcBones

    The list of bones[] should only be built and modified from within here
==============
*/
void R_CalcBones(mdsHeader_t *header, const refEntity_t *refent, int *boneList, int numBones)
{
	int   i;
	int   *boneRefs;
	float torsoWeight;

	// if the entity has changed since the last time the bones were built, reset them
	if (memcmp(&lastBoneEntity, refent, sizeof(refEntity_t)))
	{
		// different, cached bones are not valid
		memset(validBones, 0, header->numBones);
		lastBoneEntity = *refent;

		// (SA) also reset these counter statics
		//----(SA)	print stats for the complete model (not per-surface)
		if (r_bonesDebug->integer == 4 && totalrt)
		{
			Ren_Print("Lod %.2f  verts %4d/%4d  tris %4d/%4d  (%.2f%%)\n",
			          lodScale,
			          totalrv,
			          totalv,
			          totalrt,
			          totalt,
			          ( float )(100.0 * totalrt) / (float) totalt);
		}
		totalrv = totalrt = totalv = totalt = 0;
	}

	memset(newBones, 0, header->numBones);

	if (refent->oldframe == refent->frame)
	{
		backlerp  = 0;
		frontlerp = 1;
	}
	else
	{
		backlerp  = refent->backlerp;
		frontlerp = 1.0f - backlerp;
	}

	if (refent->oldTorsoFrame == refent->torsoFrame)
	{
		torsoBacklerp  = 0;
		torsoFrontlerp = 1;
	}
	else
	{
		torsoBacklerp  = refent->torsoBacklerp;
		torsoFrontlerp = 1.0f - torsoBacklerp;
	}

	frameSize = (int) (sizeof(mdsFrame_t) + (header->numBones - 1) * sizeof(mdsBoneFrameCompressed_t));

	frame = ( mdsFrame_t * )((byte *)header + header->ofsFrames +
	                         refent->frame * frameSize);
	torsoFrame = ( mdsFrame_t * )((byte *)header + header->ofsFrames +
	                              refent->torsoFrame * frameSize);
	oldFrame = ( mdsFrame_t * )((byte *)header + header->ofsFrames +
	                            refent->oldframe * frameSize);
	oldTorsoFrame = ( mdsFrame_t * )((byte *)header + header->ofsFrames +
	                                 refent->oldTorsoFrame * frameSize);

	// lerp all the needed bones (torsoParent is always the first bone in the list)
	cBoneList      = frame->bones;
	cBoneListTorso = torsoFrame->bones;

	boneInfo = ( mdsBoneInfo_t * )((byte *)header + header->ofsBones);
	boneRefs = boneList;
	//
	Matrix3Transpose(refent->torsoAxis, torsoAxis);

#ifdef HIGH_PRECISION_BONES
	if (qtrue)
	{
#else
	if (!backlerp && !torsoBacklerp)
	{
#endif
		for (i = 0; i < numBones; i++, boneRefs++)
		{
			if (validBones[*boneRefs])
			{
				// this bone is still in the cache
				bones[*boneRefs] = rawBones[*boneRefs];
				continue;
			}

			// find our parent, and make sure it has been calculated
			if ((boneInfo[*boneRefs].parent >= 0) && (!validBones[boneInfo[*boneRefs].parent] && !newBones[boneInfo[*boneRefs].parent]))
			{
				R_CalcBone(header, refent, boneInfo[*boneRefs].parent);
			}

			R_CalcBone(header, refent, *boneRefs);
		}
	}
	else        // interpolated
	{
		cOldBoneList      = oldFrame->bones;
		cOldBoneListTorso = oldTorsoFrame->bones;

		for (i = 0; i < numBones; i++, boneRefs++)
		{
			if (validBones[*boneRefs])
			{
				// this bone is still in the cache
				bones[*boneRefs] = rawBones[*boneRefs];
				continue;
			}

			// find our parent, and make sure it has been calculated
			if ((boneInfo[*boneRefs].parent >= 0) && (!validBones[boneInfo[*boneRefs].parent] && !newBones[boneInfo[*boneRefs].parent]))
			{
				R_CalcBoneLerp(header, refent, boneInfo[*boneRefs].parent);
			}

			R_CalcBoneLerp(header, refent, *boneRefs);
		}
	}

	// adjust for torso rotations
	torsoWeight = 0;
	boneRefs    = boneList;
	for (i = 0; i < numBones; i++, boneRefs++)
	{
		thisBoneInfo = &boneInfo[*boneRefs];
		bonePtr      = &bones[*boneRefs];
		// add torso rotation
		if (thisBoneInfo->torsoWeight > 0)
		{
			if (!newBones[*boneRefs])
			{
				// just copy it back from the previous calc
				bones[*boneRefs] = oldBones[*boneRefs];
				continue;
			}

			if (!(thisBoneInfo->flags & BONEFLAG_TAG))
			{
				// 1st multiply with the bone->matrix
				// 2nd translation for rotation relative to bone around torso parent offset
				VectorSubtract(bonePtr->translation, torsoParentOffset, t);
				Matrix4FromAxisPlusTranslation(bonePtr->matrix, t, m1);
				// 3rd scaled rotation
				// 4th translate back to torso parent offset
				// use previously created matrix if available for the same weight
				if (torsoWeight != thisBoneInfo->torsoWeight)
				{
					Matrix4FromScaledAxisPlusTranslation(torsoAxis, thisBoneInfo->torsoWeight, torsoParentOffset, m2);
					torsoWeight = thisBoneInfo->torsoWeight;
				}
				// multiply matrices to create one matrix to do all calculations
				Matrix4MultiplyInto3x3AndTranslation(m2, m1, bonePtr->matrix, bonePtr->translation);

			}
			else        // tag's require special handling
			{   // rotate each of the axis by the torsoAngles
				LocalScaledMatrixTransformVector(bonePtr->matrix[0], thisBoneInfo->torsoWeight, torsoAxis, tmpAxis[0]);
				LocalScaledMatrixTransformVector(bonePtr->matrix[1], thisBoneInfo->torsoWeight, torsoAxis, tmpAxis[1]);
				LocalScaledMatrixTransformVector(bonePtr->matrix[2], thisBoneInfo->torsoWeight, torsoAxis, tmpAxis[2]);
				memcpy(bonePtr->matrix, tmpAxis, sizeof(tmpAxis));

				// rotate the translation around the torsoParent
				VectorSubtract(bonePtr->translation, torsoParentOffset, t);
				LocalScaledMatrixTransformVector(t, thisBoneInfo->torsoWeight, torsoAxis, bonePtr->translation);
				VectorAdd(bonePtr->translation, torsoParentOffset, bonePtr->translation);
			}
		}
	}

	// backup the final bones
	memcpy(oldBones, bones, sizeof(bones[0]) * header->numBones);
}

#ifdef DBG_PROFILE_BONES
#define DBG_SHOWTIME    Ren_Print("%i: %i, ", di++, (dt = ri.Milliseconds()) - ldt); ldt = dt;
#else
#define DBG_SHOWTIME    ;
#endif

/*
==============
RB_SurfaceAnim
==============
*/
void RB_SurfaceAnim(mdsSurface_t *surface)
{
	int         j, k;
	refEntity_t *refent;
	int         *boneList;
	mdsHeader_t *header;

#ifdef DBG_PROFILE_BONES
	int di = 0, dt, ldt;

	dt  = ri.Milliseconds();
	ldt = dt;
#endif

	refent   = &backEnd.currentEntity->e;
	boneList = ( int * )((byte *)surface + surface->ofsBoneReferences);
	header   = ( mdsHeader_t * )((byte *)surface + surface->ofsHeader);

	R_CalcBones(header, (const refEntity_t *)refent, boneList, surface->numBoneReferences);

	DBG_SHOWTIME

	// calculate LOD
	// TODO: lerp the radius and origin
	VectorAdd(refent->origin, frame->localOrigin, vec);
	lodRadius = frame->radius;
	lodScale  = RB_CalcMDSLod(refent, vec, lodRadius, header->lodBias, header->lodScale);


//DBG_SHOWTIME

	// modification to allow dead skeletal bodies to go below minlod (experiment)
	if (refent->reFlags & REFLAG_DEAD_LOD)
	{
		if (lodScale < 0.35)       // allow dead to lod down to 35% (even if below surf->minLod) (%35 is arbitrary and probably not good generally.  worked for the blackguard/infantry as a test though)
		{
			lodScale = 0.35;
		}
		render_count = ROUND_INT((float) surface->numVerts * lodScale);

	}
	else
	{
		render_count = ROUND_INT((float) surface->numVerts * lodScale);
		if (render_count < surface->minLod)
		{
			if (!(refent->reFlags & REFLAG_DEAD_LOD))
			{
				render_count = surface->minLod;
			}
		}
	}

	if (render_count > surface->numVerts)
	{
		render_count = surface->numVerts;
	}

	RB_CheckOverflow(render_count, surface->numTriangles);

//DBG_SHOWTIME

	// setup triangle list
	RB_CheckOverflow(surface->numVerts, surface->numTriangles * 3);

//DBG_SHOWTIME

	collapse_map = ( int * )(( byte * )surface + surface->ofsCollapseMap);
	triangles    = ( int * )((byte *)surface + surface->ofsTriangles);
	indexes      = surface->numTriangles * 3;
	baseIndex    = tess.numIndexes;
	baseVertex   = tess.numVertexes;
	oldIndexes   = baseIndex;

	tess.numVertexes += render_count;

	pIndexes = &tess.indexes[baseIndex];

//DBG_SHOWTIME

	if (render_count == surface->numVerts)
	{
		memcpy(pIndexes, triangles, sizeof(triangles[0]) * indexes);
		if (baseVertex)
		{
			glIndex_t *indexesEnd;
			for (indexesEnd = pIndexes + indexes ; pIndexes < indexesEnd ; pIndexes++)
			{
				*pIndexes += baseVertex;
			}
		}
		tess.numIndexes += indexes;
	}
	else
	{
		int *collapseEnd;

		pCollapse = collapse;
		for (j = 0; j < render_count; pCollapse++, j++)
		{
			*pCollapse = j;
		}

		pCollapseMap = &collapse_map[render_count];
		for (collapseEnd = collapse + surface->numVerts ; pCollapse < collapseEnd; pCollapse++, pCollapseMap++)
		{
			*pCollapse = collapse[*pCollapseMap];
		}

		for (j = 0 ; j < indexes ; j += 3)
		{
			p0 = collapse[*(triangles++)];
			p1 = collapse[*(triangles++)];
			p2 = collapse[*(triangles++)];

			// FIXME
			// note:  serious optimization opportunity here,
			//  by sorting the triangles the following "continue"
			//  could have been made into a "break" statement.
			if (p0 == p1 || p1 == p2 || p2 == p0)
			{
				continue;
			}

			*(pIndexes++)    = baseVertex + p0;
			*(pIndexes++)    = baseVertex + p1;
			*(pIndexes++)    = baseVertex + p2;
			tess.numIndexes += 3;
		}

		baseIndex = tess.numIndexes;
	}

//DBG_SHOWTIME

	// deform the vertexes by the lerped bones

	numVerts   = surface->numVerts;
	v          = ( mdsVertex_t * )((byte *)surface + surface->ofsVerts);
	tempVert   = ( float * )(tess.xyz + baseVertex);
	tempNormal = ( float * )(tess.normal + baseVertex);
	for (j = 0; j < render_count; j++, tempVert += 4, tempNormal += 4)
	{
		mdsWeight_t *w;

		VectorClear(tempVert);

		w = v->weights;
		for (k = 0 ; k < v->numWeights ; k++, w++)
		{
			bone = &bones[w->boneIndex];
			LocalAddScaledMatrixTransformVectorTranslate(w->offset, w->boneWeight, bone->matrix, bone->translation, tempVert);
		}

		LocalMatrixTransformVector(v->normal, bones[v->weights[0].boneIndex].matrix, tempNormal);

		tess.texCoords0[baseVertex + j].v[0] = v->texCoords[0];
		tess.texCoords0[baseVertex + j].v[1] = v->texCoords[1];

		v = (mdsVertex_t *)&v->weights[v->numWeights];
	}

	DBG_SHOWTIME

	if (r_bonesDebug->integer)
	{
		if (r_bonesDebug->integer < 3)
		{
			int i;

			// DEBUG: show the bones as a stick figure with axis at each bone
			boneRefs = ( int * )((byte *)surface + surface->ofsBoneReferences);
			for (i = 0; i < surface->numBoneReferences; i++, boneRefs++)
			{
				bonePtr = &bones[*boneRefs];

				GL_Bind(tr.whiteImage);
				qglLineWidth(1);
#if 0
				// TODO: OpenGL ES renderer
				qglBegin(GL_LINES);
				for (j = 0; j < 3; j++)
				{
					VectorClear(vec);
					vec[j] = 1;
					qglColor3fv(vec);
					qglVertex3fv(bonePtr->translation);
					VectorMA(bonePtr->translation, 5, bonePtr->matrix[j], vec);
					qglVertex3fv(vec);
				}
				qglEnd();
#endif // 0
				// connect to our parent if it's valid
				if (validBones[boneInfo[*boneRefs].parent])
				{
					qglLineWidth(2);
#if 0
					// TODO: OpenGL ES renderer
					qglBegin(GL_LINES);
					qglColor3f(.6, .6, .6);
					qglVertex3fv(bonePtr->translation);
					qglVertex3fv(bones[boneInfo[*boneRefs].parent].translation);
					qglEnd();
#endif
				}

				qglLineWidth(1);
			}
		}

		if (r_bonesDebug->integer == 3 || r_bonesDebug->integer == 4)
		{
			int render_indexes = (tess.numIndexes - oldIndexes);

			// show mesh edges
			tempVert   = ( float * )(tess.xyz + baseVertex);
			tempNormal = ( float * )(tess.normal + baseVertex);

			GL_Bind(tr.whiteImage);
			qglLineWidth(1);
#if 0
			// TODO: OpenGL ES renderer
			qglBegin(GL_LINES);
			qglColor3f(.0, .0, .8);

			pIndexes = &tess.indexes[oldIndexes];
			for (j = 0; j < render_indexes / 3; j++, pIndexes += 3)
			{
				qglVertex3fv(tempVert + 4 * pIndexes[0]);
				qglVertex3fv(tempVert + 4 * pIndexes[1]);

				qglVertex3fv(tempVert + 4 * pIndexes[1]);
				qglVertex3fv(tempVert + 4 * pIndexes[2]);

				qglVertex3fv(tempVert + 4 * pIndexes[2]);
				qglVertex3fv(tempVert + 4 * pIndexes[0]);
			}

			qglEnd();
#endif // 0

			// track debug stats
			if (r_bonesDebug->integer == 4)
			{
				totalrv += render_count;
				totalrt += render_indexes / 3;
				totalv  += surface->numVerts;
				totalt  += surface->numTriangles;
			}

			if (r_bonesDebug->integer == 3)
			{
				Ren_Print("Lod %.2f  verts %4d/%4d  tris %4d/%4d  (%.2f%%)\n", lodScale, render_count, surface->numVerts, render_indexes / 3, surface->numTriangles,
				          ( float )(100.0 * render_indexes / 3) / (float) surface->numTriangles);
			}
		}
	}

	if (r_bonesDebug->integer > 1)
	{
		// dont draw the actual surface
		tess.numIndexes  = oldIndexes;
		tess.numVertexes = baseVertex;
		return;
	}

#ifdef DBG_PROFILE_BONES
	Ren_Print("\n");
#endif
}
Esempio n. 10
0
static	void RemoveIfColinear( optVertex_t *ov, optIsland_t *island ) {
	optEdge_t	*e, *e1, *e2;
	optVertex_t *v1, *v2, *v3;
	idVec3		dir1, dir2;
	float		dist;
	idVec3		point;
	idVec3		offset;
	float		off;

	v2 = ov;

	// we must find exactly two edges before testing for colinear
	e1 = NULL;
	e2 = NULL;
	for ( e = ov->edges ; e ; ) {
		if ( !e1 ) {
			e1 = e;
		} else if ( !e2 ) {
			e2 = e;
		} else {
			return;		// can't remove a vertex with three edges
		}
		if ( e->v1 == v2 ) {
			e = e->v1link;
		} else if ( e->v2 == v2 ) {
			e = e->v2link;
		} else {
			common->Error( "RemoveIfColinear: mislinked edge" );
			return;
		}
	}

	// can't remove if no edges
	if ( !e1 ) {
		return;
	}

	if ( !e2 ) {
		// this may still happen legally when a tiny triangle is
		// the only thing in a group
		common->Printf( "WARNING: vertex with only one edge\n" );
		return;
	}

	if ( e1->v1 == v2 ) {
		v1 = e1->v2;
	} else if ( e1->v2 == v2 ) {
		v1 = e1->v1;
	} else {
		common->Error( "RemoveIfColinear: mislinked edge" );
		return;
	}
	if ( e2->v1 == v2 ) {
		v3 = e2->v2;
	} else if ( e2->v2 == v2 ) {
		v3 = e2->v1;
	} else {
		common->Error( "RemoveIfColinear: mislinked edge" );
		return;
	}

	if ( v1 == v3 ) {
		common->Error( "RemoveIfColinear: mislinked edge" );
		return;
	}

	// they must point in opposite directions
	dist = ( v3->pv - v2->pv ) * ( v1->pv - v2->pv );
	if ( dist >= 0 ) {
		return;
	}

	// see if they are colinear
	VectorSubtract( v3->v.xyz, v1->v.xyz, dir1 );
	dir1.Normalize();
	VectorSubtract( v2->v.xyz, v1->v.xyz, dir2 );
	dist = DotProduct( dir2, dir1 );
	VectorMA( v1->v.xyz, dist, dir1, point );
	VectorSubtract( point, v2->v.xyz, offset );
	off = offset.Length();

	if ( off > COLINEAR_EPSILON ) {
		return;
	}

	if ( dmapGlobals.drawflag ) {
		qglBegin( GL_LINES );
		qglColor3f( 1, 1, 0 );
		qglVertex3fv( v1->pv.ToFloatPtr() );
		qglVertex3fv( v2->pv.ToFloatPtr() );
		qglEnd();
		qglFlush();
		qglBegin( GL_LINES );
		qglColor3f( 0, 1, 1 );
		qglVertex3fv( v2->pv.ToFloatPtr() );
		qglVertex3fv( v3->pv.ToFloatPtr() );
		qglEnd();
		qglFlush();
	}

	// replace the two edges with a single edge
	UnlinkEdge( e1, island );
	UnlinkEdge( e2, island );

	// v2 should have no edges now
	if ( v2->edges ) {
		common->Error( "RemoveIfColinear: didn't remove properly" );
		return;
	}


	// if there is an existing edge that already
	// has these exact verts, we have just collapsed a
	// sliver triangle out of existance, and all the edges
	// can be removed
	for ( e = island->edges ; e ; e = e->islandLink ) {
		if ( ( e->v1 == v1 && e->v2 == v3 )
		|| ( e->v1 == v3 && e->v2 == v1 ) ) {
			UnlinkEdge( e, island );
			RemoveIfColinear( v1, island );
			RemoveIfColinear( v3, island );
			return;
		}
	}

	// if we can't add the combined edge, link
	// the originals back in
	if ( !TryAddNewEdge( v1, v3, island ) ) {
		e1->islandLink = island->edges;
		island->edges = e1;
		LinkEdge( e1 );

		e2->islandLink = island->edges;
		island->edges = e2;
		LinkEdge( e2 );
		return;
	}

	// recursively try to combine both verts now,
	// because things may have changed since the last combine test
	RemoveIfColinear( v1, island );
	RemoveIfColinear( v3, island );
}
Esempio n. 11
0
void R_RenderShadowEdges( void ) {
	int		i;
	int		c;
	int		j;
	int		i2;
#if 0
	int		c_edges, c_rejected;
	int		c2, k;
	int		hit[2];
#endif
#ifdef _STENCIL_REVERSE
	int		numTris;
	int		o1, o2, o3;
#endif

	// an edge is NOT a silhouette edge if its face doesn't face the light,
	// or if it has a reverse paired edge that also faces the light.
	// A well behaved polyhedron would have exactly two faces for each edge,
	// but lots of models have dangling edges or overfanned edges
#if 0
	c_edges = 0;
	c_rejected = 0;
#endif

	for ( i = 0 ; i < tess.numVertexes ; i++ ) {
		c = numEdgeDefs[ i ];
		for ( j = 0 ; j < c ; j++ ) {
			if ( !edgeDefs[ i ][ j ].facing ) {
				continue;
			}

			//with this system we can still get edges shared by more than 2 tris which
			//produces artifacts including seeing the shadow through walls. So for now
			//we are going to render all edges even though it is a tiny bit slower. -rww
#if 1
			i2 = edgeDefs[ i ][ j ].i2;
			qglBegin( GL_TRIANGLE_STRIP );
				qglVertex3fv( tess.xyz[ i ] );
				qglVertex3fv( tess.xyz[ i + tess.numVertexes ] );
				qglVertex3fv( tess.xyz[ i2 ] );
				qglVertex3fv( tess.xyz[ i2 + tess.numVertexes ] );
			qglEnd();
#else
			hit[0] = 0;
			hit[1] = 0;

			i2 = edgeDefs[ i ][ j ].i2;
			c2 = numEdgeDefs[ i2 ];
			for ( k = 0 ; k < c2 ; k++ ) {
				if ( edgeDefs[ i2 ][ k ].i2 == i ) {
					hit[ edgeDefs[ i2 ][ k ].facing ]++;
				}
			}

			// if it doesn't share the edge with another front facing
			// triangle, it is a sil edge
			if (hit[1] != 1)
			{
				qglBegin( GL_TRIANGLE_STRIP );
				qglVertex3fv( tess.xyz[ i ] );
				qglVertex3fv( tess.xyz[ i + tess.numVertexes ] );
				qglVertex3fv( tess.xyz[ i2 ] );
				qglVertex3fv( tess.xyz[ i2 + tess.numVertexes ] );
				qglEnd();
				c_edges++;
			} else {
				c_rejected++;
			}
#endif
		}
	}

#ifdef _STENCIL_REVERSE
	//Carmack Reverse<tm> method requires that volumes
	//be capped properly -rww
	numTris = tess.numIndexes / 3;

	for ( i = 0 ; i < numTris ; i++ )
	{
		if ( !facing[i] )
		{
			continue;
		}

		o1 = tess.indexes[ i*3 + 0 ];
		o2 = tess.indexes[ i*3 + 1 ];
		o3 = tess.indexes[ i*3 + 2 ];

		qglBegin(GL_TRIANGLES);
			qglVertex3fv(tess.xyz[o1]);
			qglVertex3fv(tess.xyz[o2]);
			qglVertex3fv(tess.xyz[o3]);
		qglEnd();
		qglBegin(GL_TRIANGLES);
			qglVertex3fv(tess.xyz[o3 + tess.numVertexes]);
			qglVertex3fv(tess.xyz[o2 + tess.numVertexes]);
			qglVertex3fv(tess.xyz[o1 + tess.numVertexes]);
		qglEnd();
	}
#endif
}
Esempio n. 12
0
void CCamWnd::Cam_Draw()
{
	brush_t	*brush;
	face_t	*face;
	float	screenaspect;
	float	yfov;
	double	start, end;
	int		i;

	/*
  FILE *f = fopen("g:/nardo/raduffy/editorhack.dat", "w");
  if (f != NULL) {
    fwrite(&m_Camera.origin[0], sizeof(float), 1, f);
    fwrite(&m_Camera.origin[1], sizeof(float), 1, f);
    fwrite(&m_Camera.origin[2], sizeof(float), 1, f);
		fwrite(&m_Camera.angles[PITCH], sizeof(float), 1, f);
		fwrite(&m_Camera.angles[YAW], sizeof(float), 1, f);
    fclose(f);
  }
	*/
	
	if (!active_brushes.next)
		return;	// not valid yet
	
	if (m_Camera.timing)
		start = Sys_DoubleTime ();
	
	//
	// clear
	//
	QE_CheckOpenGLForErrors();
	
	qglViewport(0, 0, m_Camera.width, m_Camera.height);
	qglScissor(0, 0, m_Camera.width, m_Camera.height);
	qglClearColor (g_qeglobals.d_savedinfo.colors[COLOR_CAMERABACK][0],
		g_qeglobals.d_savedinfo.colors[COLOR_CAMERABACK][1],
		g_qeglobals.d_savedinfo.colors[COLOR_CAMERABACK][2], 0);
	qglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	
	//
	// set up viewpoint
	//
	vec5_t lightPos;
	
	if (g_PrefsDlg.m_bGLLighting)
	{
		qglEnable(GL_LIGHTING);
		//qglEnable(GL_LIGHT0);
		
		lightPos[0] = lightPos[1] = lightPos[2] = 3.5;
		lightPos[3] = 1.0;
		qglLightModelfv(GL_LIGHT_MODEL_AMBIENT, lightPos);
		//qglLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
		//lightPos[0] = lightPos[1] = lightPos[2] = 3.5;
    //qglLightfv(GL_LIGHT0, GL_AMBIENT, lightPos);
	}
	else
	{
		qglDisable(GL_LIGHTING);
	}
	
	qglMatrixMode(GL_PROJECTION);
	qglLoadIdentity ();
	
	screenaspect = (float)m_Camera.width / m_Camera.height;
	yfov = 2*atan((float)m_Camera.height / m_Camera.width)*180/Q_PI;
	qgluPerspective (yfov,  screenaspect,  2,  8192);
	
	qglRotatef (-90,  1, 0, 0);	    // put Z going up
	qglRotatef (90,  0, 0, 1);	    // put Z going up
	qglRotatef (m_Camera.angles[0],  0, 1, 0);
	qglRotatef (-m_Camera.angles[1],  0, 0, 1);
	qglTranslatef (-m_Camera.origin[0],  -m_Camera.origin[1],  -m_Camera.origin[2]);
	
	Cam_BuildMatrix ();
	
	
	//if (m_Camera.draw_mode == cd_light)
	//{
//	if (g_PrefsDlg.m_bGLLighting)
//	{
//		VectorCopy(m_Camera.origin, lightPos);
//		lightPos[3] = 1;
//		qglLightfv(GL_LIGHT0, GL_POSITION, lightPos);
//	}
	//}
	
	InitCull ();
	
	//
	// draw stuff
	//
	GLfloat lAmbient[] = {1.0, 1.0, 1.0, 1.0};
	
	switch (m_Camera.draw_mode)
	{
	case cd_wire:
		qglPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
		qglDisable(GL_TEXTURE_2D);
		qglDisable(GL_TEXTURE_1D);
		qglDisable(GL_BLEND);
		qglDisable(GL_DEPTH_TEST);
		qglColor3f(1.0, 1.0, 1.0);
		//		qglEnable (GL_LINE_SMOOTH);
		break;
		
	case cd_solid:
		qglCullFace(GL_FRONT);
		qglEnable(GL_CULL_FACE);
		qglShadeModel (GL_FLAT);
		qglPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
		qglDisable(GL_TEXTURE_2D);
		qglDisable(GL_BLEND);
		qglEnable(GL_DEPTH_TEST);
		qglDepthFunc (GL_LEQUAL);
		break;
		
	case cd_texture:
		qglCullFace(GL_FRONT);
		qglEnable(GL_CULL_FACE);
		qglShadeModel (GL_FLAT);
		qglPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
		qglEnable(GL_TEXTURE_2D);
		qglTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
		qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
		qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
		qglDisable(GL_BLEND);
		qglEnable(GL_DEPTH_TEST);
		qglDepthFunc (GL_LEQUAL);
		break;
		
	case cd_blend:
		qglCullFace(GL_FRONT);
		qglEnable(GL_CULL_FACE);
		qglShadeModel (GL_FLAT);
		qglPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
		qglEnable(GL_TEXTURE_2D);
		qglTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
		qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
		qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
		qglDisable(GL_DEPTH_TEST);
		qglEnable (GL_BLEND);
		qglBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
		break;
	}
	
	qglMatrixMode(GL_TEXTURE);
	
	m_nNumTransBrushes = 0;
	
	for (brush = active_brushes.next ; brush != &active_brushes ; brush=brush->next)
	{
		//DrawLightRadius(brush);
		
		if (CullBrush (brush))
			continue;
		
		if (FilterBrush (brush))
			continue;
		
		if ((brush->brush_faces->texdef.flags & (SURF_TRANS33 | SURF_TRANS66)) || (brush->brush_faces->d_texture->bFromShader && brush->brush_faces->d_texture->fTrans != 1.0))
		{
			m_TransBrushes [ m_nNumTransBrushes++ ] = brush;
		} 
		else 
		{
			//--      if (brush->patchBrush)
			//--			  m_TransBrushes [ m_nNumTransBrushes++ ] = brush;
			//--      else
			Brush_Draw(brush);
		}
		
		
	}
	
	if (g_PrefsDlg.m_bGLLighting)
	{
		qglDisable (GL_LIGHTING);
	}
	
	//
	//qglDepthMask ( 0 ); // Don't write to depth buffer
	qglEnable ( GL_BLEND );
	qglBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	for ( i = 0; i < m_nNumTransBrushes; i++ ) 
		Brush_Draw (m_TransBrushes[i]);
	
	//qglDepthMask ( 1 ); // Ok, write now
	
	qglMatrixMode(GL_PROJECTION);
	
	//
	// now draw selected brushes
	//
	
	if (g_PrefsDlg.m_bGLLighting)
	{
		qglEnable (GL_LIGHTING);
	}
	
	qglTranslatef (g_qeglobals.d_select_translate[0], g_qeglobals.d_select_translate[1], g_qeglobals.d_select_translate[2]);
	qglMatrixMode(GL_TEXTURE);
	
	brush_t* pList = (g_bClipMode && g_pSplitList) ? g_pSplitList : &selected_brushes;
	// draw normally
	for (brush = pList->next ; brush != pList ; brush=brush->next)
	{
		//DrawLightRadius(brush);
		//if (brush->patchBrush && g_qeglobals.d_select_mode == sel_curvepoint)
		//  continue;
		
		Brush_Draw(brush);
	}
	
	// blend on top
	qglMatrixMode(GL_PROJECTION);
	
	
	qglDisable (GL_LIGHTING);
	qglColor4f(1.0, 0.0, 0.0, 0.3);
	qglEnable (GL_BLEND);
	qglPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
	qglBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	qglDisable (GL_TEXTURE_2D);
	for (brush = pList->next ; brush != pList ; brush=brush->next)
	{
		if ( (brush->patchBrush && g_qeglobals.d_select_mode == sel_curvepoint) || 
			(brush->terrainBrush && g_qeglobals.d_select_mode == sel_terrainpoint) )
			continue;
		
		for (face=brush->brush_faces ; face ; face=face->next)
			Face_Draw( face );
	}
	
 
  int nCount = g_ptrSelectedFaces.GetSize();
	if (nCount > 0)
  {
    for (int i = 0; i < nCount; i++)
    {
      face_t *selFace = reinterpret_cast<face_t*>(g_ptrSelectedFaces.GetAt(i));
		  Face_Draw(selFace);
    }
  }
		
	// non-zbuffered outline
	
	qglDisable (GL_BLEND);
	qglDisable (GL_DEPTH_TEST);
	qglPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
	qglColor3f (1, 1, 1);
	for (brush = pList->next ; brush != pList ; brush=brush->next)
	{
		if (g_qeglobals.dontDrawSelectedOutlines || (brush->patchBrush && g_qeglobals.d_select_mode == sel_curvepoint) ||
			(brush->terrainBrush && g_qeglobals.d_select_mode == sel_terrainpoint))
			continue;
		
		for (face=brush->brush_faces ; face ; face=face->next)
			Face_Draw( face );
	}
	
	
	// edge / vertex flags
	
	if (g_qeglobals.d_select_mode == sel_vertex)
	{
		qglPointSize (4);
		qglColor3f (0,1,0);
		qglBegin (GL_POINTS);
		for (i=0 ; i<g_qeglobals.d_numpoints ; i++)
			qglVertex3fv (g_qeglobals.d_points[i]);
		qglEnd ();
		qglPointSize (1);
	}
	else if (g_qeglobals.d_select_mode == sel_edge)
	{
		float	*v1, *v2;
		
		qglPointSize (4);
		qglColor3f (0,0,1);
		qglBegin (GL_POINTS);
		for (i=0 ; i<g_qeglobals.d_numedges ; i++)
		{
			v1 = g_qeglobals.d_points[g_qeglobals.d_edges[i].p1];
			v2 = g_qeglobals.d_points[g_qeglobals.d_edges[i].p2];
			qglVertex3f ( (v1[0]+v2[0])*0.5,(v1[1]+v2[1])*0.5,(v1[2]+v2[2])*0.5);
		}
		qglEnd ();
		qglPointSize (1);
	}
	
	
	g_splineList->draw(static_cast<qboolean>(g_qeglobals.d_select_mode == sel_addpoint || g_qeglobals.d_select_mode == sel_editpoint));
	if (g_qeglobals.selectObject && (g_qeglobals.d_select_mode == sel_addpoint || g_qeglobals.d_select_mode == sel_editpoint)) {
		g_qeglobals.selectObject->drawSelection();
	}

	//
	// draw pointfile
	//

	qglEnable(GL_DEPTH_TEST);
	

	DrawPathLines ();
	
	
	
	if (g_qeglobals.d_pointfile_display_list)
	{
		Pointfile_Draw();
		//		glCallList (g_qeglobals.d_pointfile_display_list);
	}
	
	// bind back to the default texture so that we don't have problems
	// elsewhere using/modifying texture maps between contexts
	qglBindTexture( GL_TEXTURE_2D, 0 );
	
#if 0
	// area selection hack
	if (g_qeglobals.d_select_mode == sel_area)
	{
		qglEnable (GL_BLEND);
		qglBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
		qglColor4f(0.0, 0.0, 1.0, 0.25);
		qglPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
		qglRectfv(g_qeglobals.d_vAreaTL, g_qeglobals.d_vAreaBR);
		qglDisable (GL_BLEND);
	}
#endif
	
	qglFinish();
	QE_CheckOpenGLForErrors();
	//	Sys_EndWait();
	if (m_Camera.timing)
	{
		end = Sys_DoubleTime ();
		Sys_Printf ("Camera: %i ms\n", (int)(1000*(end-start)));
	}
}
Esempio n. 13
0
/*
=============
EmitWaterPolys

Does a water warp on the pre-fragmented glpoly_t chain
NeVo - cleaned this function up
=============
*/
void EmitWaterPolys (msurface_t *fa)
{
	glpoly_t	*p, *bp;
	float		*v;
	int			i;
	float		s, t, os, ot;
	float		scroll;
	float		rdt = r_newrefdef.time;

	if (fa->texinfo->flags & SURF_FLOWING)
		scroll = -64 * ( (rdt*0.5) - (int)(rdt*0.5) );
	else
		scroll = 0;
	for (bp=fa->polys ; bp ; bp=bp->next)
	{
		p = bp;

		qglBegin (GL_TRIANGLE_FAN);
		for (i=0,v=p->verts[0] ; i<p->numverts ; i++, v+=VERTEXSIZE)
		{
			os = v[3];
			ot = v[4];

#if !id386
			s = os + r_turbsin[(int)((ot*0.125+rdt) * TURBSCALE) & 255];
#else
			s = os + r_turbsin[Q_ftol( ((ot*0.125+rdt) * TURBSCALE) ) & 255];
#endif
			s += scroll;
			s *= (1.0/64);

#if !id386
			t = ot + r_turbsin[(int)((os*0.125+rdt) * TURBSCALE) & 255];
#else
			t = ot + r_turbsin[Q_ftol( ((os*0.125+rdt) * TURBSCALE) ) & 255];
#endif
			t *= (1.0/64);

			//		--==OBSIDIAN UPDATE==--
			//Adding this glColor call to lessen the alpha transparency on the water. Murky
			//water should not be so see through.
			//qglColor4f(1.0, 1.0, 1.0, 0.75);
			qglColor4f ( 1 - 0.3333, 1 - 0.4511, 1 - 0.5451, 0.75);	// NeVo - made color match murky fog

			qglTexCoord2f (s, t);

			//=============== Water waves ============
			//if (!(fa->texinfo->flags & SURF_FLOWING))	// NeVo - allow warping while flowing
			if (r_fluidwaves->value > 1.0)
			{
				vec3_t	nv;
				nv[0] = v[0];
				nv[1] = v[1];
				nv[2] = v[2] 
						+ r_fluidwaves->value 
						* sin( v[0] * 0.025 + rdt )
						* sin( v[2] * 0.05 + rdt )
						+ r_fluidwaves->value 
						*sin( v[1] * 0.025 + rdt * 2 )
						*sin( v[2] * 0.05 + rdt );
				qglVertex3fv (nv);
			}
			else
			//============= Water waves end. ==============
				qglVertex3fv (v);
		}
		qglEnd ();
	}
}
Esempio n. 14
0
void QueueDraw(){
	guint32 i, k;
	face_t *face;
	winding_t *w;
	int j, nDrawMode = g_pParentWnd->GetCamera().draw_mode;

	if ( notex_faces->len ) {
		qglDisable( GL_TEXTURE_2D );

		for ( i = 0; i < notex_faces->len; i++ )
		{
			face = (face_t*)notex_faces->pdata[i];
			w = face->face_winding;

			qglBegin( GL_POLYGON );

			/*
			   if (b->patchBrush)
			   //++timo FIXME: find a use case for this??
			   qglColor4f (face->d_color[0], face->d_color[1], face->d_color[2], 0.13);
			   else
			 */
			qglColor4f( face->d_color[0], face->d_color[1], face->d_color[2], face->pShader->getTrans() );

			if ( g_PrefsDlg.m_bGLLighting ) {
				qglNormal3fv( face->plane.normal );
			}

			for ( j = 0; j < w->numpoints; j++ )
			{
				if ( nDrawMode == cd_texture || nDrawMode == cd_light ) {
					qglTexCoord2fv( &w->points[j][3] );
				}
				qglVertex3fv( w->points[j] );
			}

			qglEnd();
		}
	}

	if ( !len ) {
		return;
	}

	if ( nDrawMode == cd_texture || nDrawMode == cd_light ) {
		qglEnable( GL_TEXTURE_2D );
	}

	for ( k = 0; k < len; k++ )
	{
		qglBindTexture( GL_TEXTURE_2D, sort[k].texture->texture_number );

		for ( i = 0; i < sort[k].faces->len; i++ )
		{
			face = (face_t*)sort[k].faces->pdata[i];
			w = face->face_winding;

			qglBegin( GL_POLYGON );
			/*
			   if (b->patchBrush)
			   //++timo FIXME: find a use case for this??
			   qglColor4f (face->d_color[0], face->d_color[1], face->d_color[2], 0.13);
			   else
			 */
			qglColor4f( face->d_color[0], face->d_color[1], face->d_color[2], face->pShader->getTrans() );

			if ( g_PrefsDlg.m_bGLLighting ) {
				qglNormal3fv( face->plane.normal );
			}

			for ( j = 0; j < w->numpoints; j++ )
			{
				if ( nDrawMode == cd_texture || nDrawMode == cd_light ) {
					qglTexCoord2fv( &w->points[j][3] );
				}
				qglVertex3fv( w->points[j] );
			}

			qglEnd();
		}
	}
	qglBindTexture( GL_TEXTURE_2D, 0 );
}
Esempio n. 15
0
/*
================
DrawNormals

Draws vertex normals for debugging
================
*/
static void DrawNormals(shaderCommands_t *input)
{
	vec3_t temp;

	GL_Bind(tr.whiteImage);
	qglColor3f(1, 1, 1);
	qglDepthRange(0, 0);    // never occluded
	GL_State(GLS_POLYMODE_LINE | GLS_DEPTHMASK_TRUE);

	// light direction
	if (r_shownormals->integer == 2)
	{
		trRefEntity_t *ent = backEnd.currentEntity;
		vec3_t        temp2;

		if (ent->e.renderfx & RF_LIGHTING_ORIGIN)
		{
			VectorSubtract(ent->e.lightingOrigin, backEnd.orientation.origin, temp2);
		}
		else
		{
			VectorClear(temp2);
		}
		temp[0] = DotProduct(temp2, backEnd.orientation.axis[0]);
		temp[1] = DotProduct(temp2, backEnd.orientation.axis[1]);
		temp[2] = DotProduct(temp2, backEnd.orientation.axis[2]);

		qglColor3f(ent->ambientLight[0] / 255, ent->ambientLight[1] / 255, ent->ambientLight[2] / 255);
		qglPointSize(5);
		qglBegin(GL_POINTS);
		qglVertex3fv(temp);
		qglEnd();
		qglPointSize(1);

		if (fabs(VectorLengthSquared(ent->lightDir) - 1.0f) > 0.2f)
		{
			qglColor3f(1, 0, 0);
		}
		else
		{
			qglColor3f(ent->directedLight[0] / 255, ent->directedLight[1] / 255, ent->directedLight[2] / 255);
		}
		qglLineWidth(3);
		qglBegin(GL_LINES);
		qglVertex3fv(temp);
		VectorMA(temp, 32, ent->lightDir, temp);
		qglVertex3fv(temp);
		qglEnd();
		qglLineWidth(1);
	}
	// normals drawing
	else
	{
		int i;

		qglBegin(GL_LINES);
		for (i = 0 ; i < input->numVertexes ; i++)
		{
			qglVertex3fv(input->xyz[i].v);
			VectorMA(input->xyz[i].v, r_normallength->value, input->normal[i].v, temp);
			qglVertex3fv(temp);
		}
		qglEnd();
	}

	qglDepthRange(0, 1);
}
Esempio n. 16
0
void R_RenderShadowEdges( void ) {
	int i;

#if 0
	int numTris;

	// dumb way -- render every triangle's edges
	numTris = tess.numIndexes / 3;

	for ( i = 0 ; i < numTris ; i++ ) {
		int i1, i2, i3;

		if ( !facing[i] ) {
			continue;
		}

		i1 = tess.indexes[ i * 3 + 0 ];
		i2 = tess.indexes[ i * 3 + 1 ];
		i3 = tess.indexes[ i * 3 + 2 ];

		qglBegin( GL_TRIANGLE_STRIP );
		qglVertex3fv( tess.xyz[ i1 ] );
		qglVertex3fv( shadowXyz[ i1 ] );
		qglVertex3fv( tess.xyz[ i2 ] );
		qglVertex3fv( shadowXyz[ i2 ] );
		qglVertex3fv( tess.xyz[ i3 ] );
		qglVertex3fv( shadowXyz[ i3 ] );
		qglVertex3fv( tess.xyz[ i1 ] );
		qglVertex3fv( shadowXyz[ i1 ] );
		qglEnd();
	}
#else
	int c, c2;
	int j, k;
	int i2;
	int c_edges, c_rejected;
	int hit[2];

	// an edge is NOT a silhouette edge if its face doesn't face the light,
	// or if it has a reverse paired edge that also faces the light.
	// A well behaved polyhedron would have exactly two faces for each edge,
	// but lots of models have dangling edges or overfanned edges
	c_edges = 0;
	c_rejected = 0;

	for ( i = 0 ; i < tess.numVertexes ; i++ ) {
		c = numEdgeDefs[ i ];
		for ( j = 0 ; j < c ; j++ ) {
			if ( !edgeDefs[ i ][ j ].facing ) {
				continue;
			}

			hit[0] = 0;
			hit[1] = 0;

			i2 = edgeDefs[ i ][ j ].i2;
			c2 = numEdgeDefs[ i2 ];
			for ( k = 0 ; k < c2 ; k++ ) {
				if ( edgeDefs[ i2 ][ k ].i2 == i ) {
					hit[ edgeDefs[ i2 ][ k ].facing ]++;
				}
			}

			// if it doesn't share the edge with another front facing
			// triangle, it is a sil edge
			if ( hit[ 1 ] == 0 ) {
				qglBegin( GL_TRIANGLE_STRIP );
				qglVertex3fv( tess.xyz[ i ] );
				qglVertex3fv( shadowXyz[ i ] );
				qglVertex3fv( tess.xyz[ i2 ] );
				qglVertex3fv( shadowXyz[ i2 ] );
				qglEnd();
				c_edges++;
			} else {
				c_rejected++;
			}
		}
	}
#endif
}
Esempio n. 17
0
void GL_DrawAliasShadow (dmdl_t *paliashdr, int posenum)
{
	dtrivertx_t	*verts;
	int		*order;
	vec3_t	point;
	float	height, lheight;
	int		count;
	daliasframe_t	*frame;

	lheight = currententity->origin[2] - lightspot[2];

	frame = (daliasframe_t *)((byte *)paliashdr + paliashdr->ofs_frames 
		+ currententity->frame * paliashdr->framesize);
	verts = frame->verts;

	height = 0;

	order = (int *)((byte *)paliashdr + paliashdr->ofs_glcmds);

	height = -lheight + 1.0;

	while (1)
	{
		// get the vertex count and primitive type
		count = *order++;
		if (!count)
			break;		// done
		if (count < 0)
		{
			count = -count;
			qglBegin (GL_TRIANGLE_FAN);
		}
		else
			qglBegin (GL_TRIANGLE_STRIP);

		do
		{
			// normals and vertexes come from the frame list

			//point[0] = verts[order[2]].v[0] * frame->scale[0] + frame->translate[0];
			//point[1] = verts[order[2]].v[1] * frame->scale[1] + frame->translate[1];
			//point[2] = verts[order[2]].v[2] * frame->scale[2] + frame->translate[2];


			memcpy( point, s_lerped[order[2]], sizeof( point )  );

			point[0] -= shadevector[0]*(point[2]+lheight);
			point[1] -= shadevector[1]*(point[2]+lheight);
			point[2] = height;
//			height -= 0.001;
			qglVertex3fv (point);

			order += 3;

//			verts++;

		} while (--count);

		qglEnd ();
	}	
}
/*
=====================
SplitOriginalEdgesAtCrossings
=====================
*/
void SplitOriginalEdgesAtCrossings( optimizeGroup_t *opt ) {
	int				i, j, k, l;
	int				numOriginalVerts;
	edgeCrossing_t	**crossings;

	numOriginalVerts = numOptVerts;
	// now split any crossing edges and create optEdges
	// linked to the vertexes

	// debug drawing bounds
	dmapGlobals.drawBounds = optBounds;

	dmapGlobals.drawBounds[0][0] -= 2;
	dmapGlobals.drawBounds[0][1] -= 2;
	dmapGlobals.drawBounds[1][0] += 2;
	dmapGlobals.drawBounds[1][1] += 2;

	// generate crossing points between all the original edges
	crossings = (edgeCrossing_t **)Mem_ClearedAlloc( numOriginalEdges * sizeof( *crossings ) );

	for ( i = 0 ; i < numOriginalEdges ; i++ ) {
		if ( dmapGlobals.drawflag ) {
			DrawOriginalEdges( numOriginalEdges, originalEdges );
			qglBegin( GL_LINES );
			qglColor3f( 0, 1, 0 );
			qglVertex3fv( originalEdges[i].v1->pv.ToFloatPtr() );
			qglColor3f( 0, 0, 1 );
			qglVertex3fv( originalEdges[i].v2->pv.ToFloatPtr() );
			qglEnd();
			qglFlush();
		}
		for ( j = i+1 ; j < numOriginalEdges ; j++ ) {
			optVertex_t	*v1, *v2, *v3, *v4;
			optVertex_t	*newVert;
			edgeCrossing_t	*cross;

			v1 = originalEdges[i].v1;
			v2 = originalEdges[i].v2;
			v3 = originalEdges[j].v1;
			v4 = originalEdges[j].v2;

			if ( !EdgesCross( v1, v2, v3, v4 ) ) {
				continue;
			}

			// this is the only point in optimization where
			// completely new points are created, and it only
			// happens if there is overlapping coplanar
			// geometry in the source triangles
			newVert = EdgeIntersection( v1, v2, v3, v4, opt );

			if ( !newVert ) {
//common->Printf( "lines %i (%i to %i) and %i (%i to %i) are colinear\n", i, v1 - optVerts, v2 - optVerts, 
//		   j, v3 - optVerts, v4 - optVerts );	// !@#
				// colinear, so add both verts of each edge to opposite
				if ( VertexBetween( v3, v1, v2 ) ) {
					cross = (edgeCrossing_t *)Mem_ClearedAlloc( sizeof( *cross ) );
					cross->ov = v3;
					cross->next = crossings[i];
					crossings[i] = cross;
				}

				if ( VertexBetween( v4, v1, v2 ) ) {
					cross = (edgeCrossing_t *)Mem_ClearedAlloc( sizeof( *cross ) );
					cross->ov = v4;
					cross->next = crossings[i];
					crossings[i] = cross;
				}

				if ( VertexBetween( v1, v3, v4 ) ) {
					cross = (edgeCrossing_t *)Mem_ClearedAlloc( sizeof( *cross ) );
					cross->ov = v1;
					cross->next = crossings[j];
					crossings[j] = cross;
				}

				if ( VertexBetween( v2, v3, v4 ) ) {
					cross = (edgeCrossing_t *)Mem_ClearedAlloc( sizeof( *cross ) );
					cross->ov = v2;
					cross->next = crossings[j];
					crossings[j] = cross;
				}

				continue;
			}
#if 0
if ( newVert && newVert != v1 && newVert != v2 && newVert != v3 && newVert != v4 ) {
common->Printf( "lines %i (%i to %i) and %i (%i to %i) cross at new point %i\n", i, v1 - optVerts, v2 - optVerts, 
		   j, v3 - optVerts, v4 - optVerts, newVert - optVerts );
} else if ( newVert ) {
common->Printf( "lines %i (%i to %i) and %i (%i to %i) intersect at old point %i\n", i, v1 - optVerts, v2 - optVerts, 
		  j, v3 - optVerts, v4 - optVerts, newVert - optVerts );
}
#endif
			if ( newVert != v1 && newVert != v2 ) {
				cross = (edgeCrossing_t *)Mem_ClearedAlloc( sizeof( *cross ) );
				cross->ov = newVert;
				cross->next = crossings[i];
				crossings[i] = cross;
			}

			if ( newVert != v3 && newVert != v4 ) {
				cross = (edgeCrossing_t *)Mem_ClearedAlloc( sizeof( *cross ) );
				cross->ov = newVert;
				cross->next = crossings[j];
				crossings[j] = cross;
			}

		}
	}


	// now split each edge by its crossing points
	// colinear edges will have duplicated edges added, but it won't hurt anything
	for ( i = 0 ; i < numOriginalEdges ; i++ ) {
		edgeCrossing_t	*cross, *nextCross;
		int				numCross;
		optVertex_t		**sorted;

		numCross = 0;
		for ( cross = crossings[i] ; cross ; cross = cross->next ) {
			numCross++;
		}
		numCross += 2;	// account for originals
		sorted = (optVertex_t **)Mem_Alloc( numCross * sizeof( *sorted ) );
		sorted[0] = originalEdges[i].v1;
		sorted[1] = originalEdges[i].v2;
		j = 2;
		for ( cross = crossings[i] ; cross ; cross = nextCross ) {
			nextCross = cross->next;
			sorted[j] = cross->ov;
			Mem_Free( cross );
			j++;
		}

		// add all possible fragment combinations that aren't divided
		// by another point
		for ( j = 0 ; j < numCross ; j++ ) {
			for ( k = j+1 ; k < numCross ; k++ ) {
				for ( l = 0 ; l < numCross ; l++ ) {
					if ( sorted[l] == sorted[j] || sorted[l] == sorted[k] ) {
						continue;
					}
					if ( sorted[j] == sorted[k] ) {
						continue;
					}
					if ( VertexBetween( sorted[l], sorted[j], sorted[k] ) ) {
						break;
					}
				}
				if ( l == numCross ) {
//common->Printf( "line %i fragment from point %i to %i\n", i, sorted[j] - optVerts, sorted[k] - optVerts );
					AddEdgeIfNotAlready( sorted[j], sorted[k] );
				}
			}
		}

		Mem_Free( sorted );
	}


	Mem_Free( crossings );
	Mem_Free( originalEdges );

	// check for duplicated edges
	for ( i = 0 ; i < numOptEdges ; i++ ) {
		for ( j = i+1 ; j < numOptEdges ; j++ ) {
			if ( ( optEdges[i].v1 == optEdges[j].v1 && optEdges[i].v2 == optEdges[j].v2 ) 
				|| ( optEdges[i].v1 == optEdges[j].v2 && optEdges[i].v2 == optEdges[j].v1 ) ) {
				common->Printf( "duplicated optEdge\n" );
			}
		}
	}

	if ( dmapGlobals.verbose ) {
		common->Printf( "%6i original edges\n", numOriginalEdges );
		common->Printf( "%6i edges after splits\n", numOptEdges );
		common->Printf( "%6i original vertexes\n", numOriginalVerts );
		common->Printf( "%6i vertexes after splits\n", numOptVerts );
	}
}
Esempio n. 19
0
void DrawTerrain( terrainMesh_t *pm, bool bPoints, bool bShade ) {
	int				i;
	int				w;
	int				h;
	int				x;
	int				y;
	//int			n;
	//float			x1;
	//float			y1;
	float			scale_x;
	float			scale_y;
	//vec3_t		pSelectedPoints[ MAX_TERRA_POINTS ];
	//int			nIndex;
	terravert_t		a0;
	terravert_t		a1;
	terravert_t		a2;
	terravert_t		b0;
	terravert_t		b1;
	terravert_t		b2;
	terrainVert_t	*vert;
	qtexture_t		*texture;

	h = pm->height - 1;
	w = pm->width - 1;
   
	scale_x = pm->scale_x;
	scale_y = pm->scale_y;

	qglShadeModel (GL_SMOOTH);

	if ( bShade ) {
		for( i = 0; i < pm->numtextures; i++ ) {
			texture = pm->textures[ i ];

			qglBindTexture( GL_TEXTURE_2D, texture->texture_number );

			vert = pm->heightmap;
			for( y = 0; y < h; y++ ) {
				qglBegin( GL_TRIANGLES );

				for( x = 0; x < w; x++, vert++ ) {
					Terrain_GetTriangles( pm, x, y, &a0, &a1, &a2, &b0, &b1, &b2, texture );

					// first tri
					if ( a0.rgba[ 3 ] || a1.rgba[ 3 ] || a2.rgba[ 3 ] ) {
						qglColor4fv( a0.rgba );
						qglTexCoord2fv( a0.tc );
						qglVertex3fv( a0.xyz );

						qglColor4fv( a1.rgba );
						qglTexCoord2fv( a1.tc );
						qglVertex3fv( a1.xyz );

						qglColor4fv( a2.rgba );
						qglTexCoord2fv( a2.tc );
						qglVertex3fv( a2.xyz );
					}

					// second tri
					if ( b0.rgba[ 3 ] || b1.rgba[ 3 ] || b2.rgba[ 3 ] ) {
						qglColor4fv( b0.rgba );
						qglTexCoord2fv( b0.tc );
						qglVertex3fv( b0.xyz );

						qglColor4fv( b1.rgba );
						qglTexCoord2fv( b1.tc );
						qglVertex3fv( b1.xyz );

						qglColor4fv( b2.rgba );
						qglTexCoord2fv( b2.tc );
						qglVertex3fv( b2.xyz );
					}
				}

			qglEnd ();
			}
		}
	} else {
		for( i = 0; i < pm->numtextures; i++ ) {
			texture = pm->textures[ i ];

			qglBindTexture( GL_TEXTURE_2D, texture->texture_number );

			vert = pm->heightmap;
			for( y = 0; y < h; y++ ) {
				qglBegin( GL_TRIANGLES );

				for( x = 0; x < w; x++, vert++ ) {
					Terrain_GetTriangles( pm, x, y, &a0, &a1, &a2, &b0, &b1, &b2, texture );

					// first tri
					if ( a0.rgba[ 3 ] || a1.rgba[ 3 ] || a2.rgba[ 3 ] ) {
						qglColor4fv( a0.rgba );
						qglTexCoord2fv( a0.tc );
						qglVertex3fv( a0.xyz );

						qglColor4fv( a1.rgba );
						qglTexCoord2fv( a1.tc );
						qglVertex3fv( a1.xyz );

						qglColor4fv( a2.rgba );
						qglTexCoord2fv( a2.tc );
						qglVertex3fv( a2.xyz );
					}

					// second tri
					if ( b0.rgba[ 3 ] || b1.rgba[ 3 ] || b2.rgba[ 3 ] ) {
						qglColor4fv( b0.rgba );
						qglTexCoord2fv( b0.tc );
						qglVertex3fv( b0.xyz );

						qglColor4fv( b1.rgba );
						qglTexCoord2fv( b1.tc );
						qglVertex3fv( b1.xyz );

						qglColor4fv( b2.rgba );
						qglTexCoord2fv( b2.tc );
						qglVertex3fv( b2.xyz );
					}
				}
				qglEnd ();
			}
		}
	}

	qglPushAttrib( GL_CURRENT_BIT );

	bool bDisabledLighting = qglIsEnabled( GL_LIGHTING );
	if ( bDisabledLighting ) {
		qglDisable( GL_LIGHTING );
	}

#if 0
	terrainVert_t	*currentrow;
	terrainVert_t	*nextrow;
	float			x2;
	float			y2;

	// Draw normals
	qglDisable( GL_TEXTURE_2D );
	qglDisable( GL_BLEND );
	qglColor3f( 1, 1, 1 );
	qglBegin( GL_LINES );

	y2 = pm->origin[ 1 ];
	nextrow = pm->heightmap;
	for( y = 0; y < h; y++ ) {
		y1 = y2;
		y2 += scale_y;

		x2 = pm->origin[ 0 ];
		currentrow = nextrow;
		nextrow = currentrow + pm->width;
		for( x = 0; x < w; x++ ) {
			x1 = x2;
			x2 += scale_x;

			// normals
			qglVertex3f( x1, y1, pm->origin[ 2 ] + currentrow[ x ].height );
			qglVertex3f( x1 + currentrow[ x ].normal[ 0 ] * 16.0f, y1 + currentrow[ x ].normal[ 1 ] * 16.0f, pm->origin[ 2 ] + currentrow[ x ].height + currentrow[ x ].normal[ 2 ] * 16.0f );

			qglVertex3f( x2, y1, pm->origin[ 2 ] + currentrow[ x + 1 ].height );
			qglVertex3f( x2 + currentrow[ x + 1 ].normal[ 0 ] * 16.0f, y1 + currentrow[ x + 1 ].normal[ 1 ] * 16.0f, pm->origin[ 2 ] + currentrow[ x + 1 ].height + currentrow[ x + 1 ].normal[ 2 ] * 16.0f );

			qglVertex3f( x1, y2, pm->origin[ 2 ] + nextrow[ x ].height );
			qglVertex3f( x1 + nextrow[ x ].normal[ 0 ] * 16.0f, y2 + nextrow[ x ].normal[ 1 ] * 16.0f, pm->origin[ 2 ] + nextrow[ x ].height + nextrow[ x ].normal[ 2 ] * 16.0f );

			qglVertex3f( x2, y2, pm->origin[ 2 ] + nextrow[ x + 1 ].height );
			qglVertex3f( x2 + nextrow[ x + 1 ].normal[ 0 ] * 16.0f, y2 + nextrow[ x + 1 ].normal[ 1 ] * 16.0f, pm->origin[ 2 ] + nextrow[ x + 1 ].height + nextrow[ x + 1 ].normal[ 2 ] * 16.0f );
		}
	}

	qglEnd ();
	qglEnable( GL_TEXTURE_2D );
#endif

#if 0
	if ( bPoints && ( g_qeglobals.d_select_mode == sel_terrainpoint || g_qeglobals.d_select_mode == sel_area ) ) {
		qglPointSize( 6 );
		qglDisable( GL_TEXTURE_2D );
		qglDisable( GL_BLEND );

		qglBegin( GL_POINTS );

		nIndex = 0;

		qglColor4f( 1, 0, 1, 1 );

		y1 = pm->origin[ 1 ];
		for ( y = 0; y < pm->height; y++, y1 += pm->scale_y ) {
			x1 = pm->origin[ 0 ];
			for( x = 0; x < pm->width; x++, x1 += pm->scale_x ) {
				// FIXME: need to not do loop lookups inside here
				n = Terrain_PointInMoveList( &pm->heightmap[ x + y * pm->width ] );
				if ( n >= 0 ) {
					VectorSet( pSelectedPoints[ nIndex ], x1, y1, pm->heightmap[ x + y * pm->width ].height + pm->origin[ 2 ] );
					nIndex++;
				} else {
					qglVertex3f( x1, y1, pm->origin[ 2 ] + pm->heightmap[ x + y * pm->width ].height );
				}
			}
		}

		qglEnd();
		
		qglEnable( GL_TEXTURE_2D );

		if ( nIndex > 0 ) {
			qglBegin( GL_POINTS );
			qglColor4f( 0, 0, 1, 1 );
			while( nIndex-- > 0 ) {
				qglVertex3fv( pSelectedPoints[ nIndex ] );
			}
		
			qglEnd();
		}
	}
#endif

	if ( g_qeglobals.d_numterrapoints && ( ( g_qeglobals.d_select_mode == sel_terrainpoint ) || ( g_qeglobals.d_select_mode == sel_terraintexture ) ) ) {
#if 0 
		qglPointSize( 6 );
		qglDisable( GL_TEXTURE_2D );
		qglDisable( GL_BLEND );

		qglBegin( GL_POINTS );

		qglColor4f( 1, 0, 1, 1 );

		for( i = 0; i < g_qeglobals.d_numterrapoints; i++ ) {
			qglVertex3fv( g_qeglobals.d_terrapoints[ i ]->xyz );
		}

		qglEnd();
			
		qglEnable( GL_TEXTURE_2D );
#endif

		brush_t			*pb;
		terrainMesh_t	*pm;

		pm = NULL;
		for( pb = active_brushes .next; pb != &active_brushes; pb = pb->next ) {
			if ( pb->terrainBrush ) {
				pm = pb->pTerrain;
				break;
			}
		}

		if ( pm ) {
			qglDisable( GL_TEXTURE_2D );
			qglBegin( GL_TRIANGLES );
			qglEnable( GL_BLEND );

			qglColor4f( 0.25, 0.5, 1, 0.35 );

			for( i = 0; i < g_qeglobals.d_numterrapoints; i++ ) {
				terravert_t		a0;
				terravert_t		a1;
				terravert_t		a2;

				qglColor4f( 0.25, 0.5, 1, g_qeglobals.d_terrapoints[ i ]->scale * 0.75 + 0.25 );
				Terrain_GetTriangle( pm, g_qeglobals.d_terrapoints[ i ]->tri.index * 2, &a0, &a1, &a2 );

				qglVertex3fv( a0.xyz );
				qglVertex3fv( a1.xyz );
				qglVertex3fv( a2.xyz );

				Terrain_GetTriangle( pm, g_qeglobals.d_terrapoints[ i ]->tri.index * 2 + 1, &a0, &a1, &a2 );

				qglVertex3fv( a0.xyz );
				qglVertex3fv( a1.xyz );
				qglVertex3fv( a2.xyz );
			}
			qglEnd();
			
			qglDisable( GL_BLEND );
			qglEnable( GL_TEXTURE_2D );
		}
	}
}