#### Archived

This topic is now archived and is closed to further replies.

# Rendering Q3 BSP curved surfaces?

This topic is 5192 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

I''m trying to find some resources on rendering curved surfaces in Quake 3 BSPs. I can''t seem to find anything except vague references to their existence, and the file header doesn''t even lend any clues to where the data is, or how I''m supposed to go about eating it. Even the Aftershock source had nothing useful. So what''s up with these curved surfaces things, and where can I get some info on loading/rendering them?

##### Share on other sites
It''s been a while since I used them, but IIRC they''re all 3x3 bezier patches. You get a set of 9 vertices, 3 rows of 3, which are your control points (with the patch anchored at the corner points); all you need to do then is tesselate it.

##### Share on other sites
If I remember, there might also be times when you get your patches served to you in 9x9 form, I just cut mine up into 3x3 patches but each to their own..

##### Share on other sites
yea, when i did them it took friggn ages, i cant remember how
exactly it was i did them, but i'll provide code from my q3
engine here.

sorry i cant be of more use, but its been so long.

i guess you can contact me and i can try answer a few questions
silvermace007#hotmail

-------------------------------------------------------------------------
data stuctures you'll need:
/// internal structure, stores information needed to generate/// the quadratic bezier surfacestruct bspPatch{				 // 3x3 grid of anchor points	 // bspVertexData stores Texture/LM control points as well bspVertexData	cp[9]; int startv, endv; int index; int tessfactor; int step; int faceid;};[source]Patch compile code:[source]//////////////////////////////////////////////////// main bezier thingo function!//////////////////////////////////////////////////float quadbasis(float s, int index){	switch(index)	{		case 0: return (1 - s) * ( 1 - s );		case 1: return  2 * s  * ( 1 - s );		case 2: return  s * s;	}	return 0.f;}//////////////////////////////////////////////////// prepares data for compilation//////////////////////////////////////////////////void CBSPMap::internBuildFaces(){	int npatchs = 0;	int nmeshes = 0;	bspPatch patch;	memset(&patch, 0, sizeof(bspPatch));	patch.tessfactor = 8;	vector<bspFaceData>::iterator face = vFaces.begin();	for(; face != vFaces.end(); face++ )	{		if( face->type == PATCH )		{			int x, y, x_axis = 0, y_axis = 0;			// set the faces vertex indicies			int temp = vVerts.size();			//face->begin_index_verts = vVerts.size();//patch.startv;			for(int size_y = 0; size_y < (face->patch_size[1] - 1)/2; size_y++)			{				for(int size_x = 0; size_x < (face->patch_size[0] - 1)/2; size_x++)				{					int cpindex = 0;					for(y = 0; y < 3; y++)					for(x = 0; x < 3; x++)					{						bspVertexData& cp = patch.cp[cpindex];						int index = face->begin_index_verts + (x + x_axis) + ((y + y_axis) * face->patch_size[0]);						cp.point[0] = vVerts[index].point[0];						cp.point[1] = vVerts[index].point[1];						cp.point[2] = vVerts[index].point[2];						cp.tc[0]	= vVerts[index].tc[0];						cp.tc[1]	= vVerts[index].tc[1];						cp.lmtc[0]  = vVerts[index].lmtc[0];						cp.lmtc[1]  = vVerts[index].lmtc[1];						//memcpy( &, &cp, sizeof(bspVertexData) );						cpindex++;					}								x_axis +=2;					// compile the patch and add it to the vertex array					internCompilepatch( patch );					//face->n_verts += patch.endv - patch.startv;				}				x_axis = 0;				y_axis +=2;			}			face->begin_index_verts = temp;			face->n_verts = vVerts.size() - face->begin_index_verts;			npatchs++;		}		else 		if( face->type == MESH )		{                // REMOVED THIS AS IT IS IRRELIVANT TO PATCHES		}	}}///////////////////////////////////////////////////Patch Compile Function:////////////////////////////////////////////////   void CBSPMap::internCompilepatch(CBSPMap::bspPatch &info){	int factor = info.tessfactor - 2;	int x,y;	int i,j;	float step;	float s,t;	float bias;	if( factor < 3 ) 		factor = 3;	step = (float)( 1.0f / (float)(factor - 1) );	vector<bspVertexData> pts( factor * factor );	memset( &pts[0], 0, sizeof(bspVertexData) * pts.size() );	for( x = 0, s = 0; x < factor; x++, s+=step)	for( y = 0, t = 0; y < factor; y++, t+=step)	{		int index = 0, cpindex = 0;		index = x + (y * factor);		for( i = 0; i<3; i++)		for( j = 0; j<3; j++)		{			cpindex = i + j * 3;			bias = quadbasis(s,i) * quadbasis(t,j);			pts[index].point[0]		+= bias * info.cp[cpindex].point[0];			pts[index].point[1]		+= bias * info.cp[cpindex].point[1];			pts[index].point[2]		+= bias * info.cp[cpindex].point[2];			// interpolate texture & lightmap coords			pts[index].tc[0]		+= bias * info.cp[cpindex].tc[0];			pts[index].tc[1]		+= bias * info.cp[cpindex].tc[1];			pts[index].lmtc[0]		+= bias * info.cp[cpindex].lmtc[0];			pts[index].lmtc[1]		+= bias * info.cp[cpindex].lmtc[1];		}		}	info.startv = vVerts.size();#ifdef _DEBUG	vector< bspVertexData >::iterator test = pts.begin();#endif	bspVertexData *pt = NULL;	int numfaces = 0, numverts = 0;	for( y = 0, t = 0; y < factor-1; y++, t += step)	{		for(x = 0, s = 0; x < factor; x++, s += step)		{			pt = &pts[x+(y*factor)];			vVerts.push_back( *pt );					numverts++;			pt = &pts[x+((y+1)*factor)];			vVerts.push_back( *pt );			numverts++;		}	}	info.endv = vVerts.size();}

EDIT: source juggling
I hate these source boxes.

[edited by - silvermace on March 6, 2004 5:49:02 AM]

##### Share on other sites
Ok, one thing...where is the bloody patch data in the file? I can''t find it, lol

##### Share on other sites
it should be just a bspFace, it will be singnaled by the fact
that the type variable of the structure will be "patch".

patches are kept in the BSP''s as faces with 9+ verts, so they
are like all the other faces, its just that the 9+ verts are
control points rather than physical verticies.

its all in the code i supplied, take a good look

• 10
• 40
• 15
• 10
• 23