Example #1
0
void Test2( void )
{
	int		i, j, k;
	int		v1, v2;
	int		tri;


	for ( i = 0; i < vertexnum; i++ )
	{
		tri = 0;
		for ( j = 0; j < verts[i].edgenum; j++ )
		{
			v1 = verts[i].edges[j];
#if 0

			fprintf( handle, "%f %f %f\n", vertices[i][0]/SCL, vertices[i][1]/SCL, vertices[i][2]/SCL );
			fprintf( handle, "%f %f %f\n", vertices[v1][0]/SCL, vertices[v1][1]/SCL, vertices[v1][2]/SCL );
			fprintf( handle, "%f %f %f\n", vertices[v1][0]/SCL, vertices[v1][1]/SCL, vertices[v1][2]/SCL );
			fprintf( handle, "\n" );

#else		       
			for ( k = 0; k < verts[i].edgenum; k++ )
			{
				if ( j == k )
					continue;
				
				v2 = verts[i].edges[k];

				if ( TestEdge( v1, v2 ) || TestEdge( v2, v1 ) )
				{
					if ( TestTri( i, v1, v2 ) ||
					     TestTri( v1, i, v2 ) ||
					     TestTri( v2, i, v1 ) )
						continue;

					AddTri( i, v1, v2 );
					AddTri( v1, i, v2 );
					AddTri( v2, i, v1 );
#if 0
					fprintf( handle, "%f %f %f\n", vertices[i][0]/SCL, vertices[i][1]/SCL, vertices[i][2]/SCL );
					fprintf( handle, "%f %f %f\n", vertices[v1][0]/SCL, vertices[v1][1]/SCL, vertices[v1][2]/SCL );
					fprintf( handle, "%f %f %f\n", vertices[v2][0]/SCL, vertices[v2][1]/SCL, vertices[v2][2]/SCL );
#else
					fprintf( handle, "%d %d %d\n", i, v1, v2 );
#endif
					fprintf( handle, "\n" );	

					tri++;
				}
			}
#endif	
		}

		printf( "v%d: %d tris\n", i, tri );	
	}

}
Example #2
0
/**
 * @note Can be recursively reentered
 */
static void TestEdge (vec_t start, vec_t end, int p1, int p2, int startvert)
{
	int k;
	vec_t dist, error;
	vec3_t	delta, exact, off, p;

	if (p1 == p2) {
		c_degenerate++;
		return;		/* degenerate edge */
	}

	for (k = startvert; k < num_edge_verts; k++) {
		const int j = edge_verts[k];
		if (j == p1 || j == p2)
			continue;

		VectorCopy(curTile->vertexes[j].point, p);

		VectorSubtract(p, edge_start, delta);
		dist = DotProduct(delta, edge_dir);
		if (dist <= start || dist >= end)
			continue;		/* off an end */
		VectorMA(edge_start, dist, edge_dir, exact);
		VectorSubtract(p, exact, off);
		error = VectorLength(off);

		if (fabs(error) > OFF_EPSILON)
			continue;		/* not on the edge */

		/* break the edge */
		c_tjunctions++;
		TestEdge(start, dist, p1, j, k + 1);
		TestEdge(dist, end, j, p2, k + 1);
		return;
	}

	/* the edge p1 to p2 is now free of tjunctions */
	if (numsuperverts >= MAX_SUPERVERTS)
		Sys_Error("MAX_SUPERVERTS (%i)", numsuperverts);
	superverts[numsuperverts] = p1;
	numsuperverts++;
}
Example #3
0
static void FixFaceEdges (node_t* node, face_t* f)
{
	int i, base;
	vec3_t e2;
	int count[MAX_SUPERVERTS], start[MAX_SUPERVERTS];

	if (f->merged || f->split[0] || f->split[1])
		return;

	numsuperverts = 0;

	for (i = 0; i < f->numpoints; i++) {
		const int p1 = f->vertexnums[i];
		const int p2 = f->vertexnums[(i + 1) % f->numpoints];

		VectorCopy(curTile->vertexes[p1].point, edge_start);
		VectorCopy(curTile->vertexes[p2].point, e2);

		FindEdgeVerts(edge_start, e2);

		VectorSubtract(e2, edge_start, edge_dir);
		vec_t len = VectorNormalize(edge_dir);

		start[i] = numsuperverts;
		TestEdge(0, len, p1, p2, 0);

		count[i] = numsuperverts - start[i];
	}

	/* entire face collapsed */
	if (numsuperverts < 3) {
		f->numpoints = 0;
		c_facecollapse++;
		return;
	}

	/* we want to pick a vertex that doesn't have tjunctions
	 * on either side, which can cause artifacts on trifans,
	 * especially underwater */
	for (i = 0; i < f->numpoints; i++) {
		if (count[i] == 1 && count[(i + f->numpoints - 1) % f->numpoints] == 1)
			break;
	}
	if (i == f->numpoints) {
		c_badstartverts++;
		base = 0;
	} else {
		/* rotate the vertex order */
		base = start[i];
	}

	/* this may fragment the face if > MAXEDGES */
	FaceFromSuperverts(node, f, base);
}
Example #4
0
void CBuild::BuildCForm	()
{
	// Collecting data
	Phase		("CFORM: creating...");
	vecFace*	cfFaces		= new vecFace();
	vecVertex*	cfVertices	= new vecVertex();
	{
		xr_vector<bool>			cfVertexMarks;
		cfVertexMarks.assign	(lc_global_data()->g_vertices().size(),false);

		Status("Sorting...");
		std::sort(lc_global_data()->g_vertices().begin(),lc_global_data()->g_vertices().end());

		Status("Collecting faces...");
		cfFaces->reserve	(lc_global_data()->g_faces().size());
		for (vecFaceIt I=lc_global_data()->g_faces().begin(); I!=lc_global_data()->g_faces().end(); ++I)
		{
			Face* F = *I;
			if (F->Shader().flags.bCollision) 
			{
				cfFaces->push_back(F);
				int index = GetVertexIndex(F->v[0]);
				cfVertexMarks[index] = true;

				index = GetVertexIndex(F->v[1]);
				cfVertexMarks[index] = true;

				index = GetVertexIndex(F->v[2]);
				cfVertexMarks[index] = true;
			}
		}

		Status("Collecting vertices...");
		cfVertices->reserve	(lc_global_data()->g_vertices().size());
		std::sort(cfFaces->begin(),cfFaces->end());
		for (u32 V=0; V<lc_global_data()->g_vertices().size(); V++)
			if (cfVertexMarks[V]) cfVertices->push_back(lc_global_data()->g_vertices()[V]);
	}

	float	p_total = 0;
	float	p_cost  = 1.f/(cfVertices->size());
	
	Fbox BB; BB.invalidate();
	for (vecVertexIt it = cfVertices->begin(); it!=cfVertices->end(); it++)
		BB.modify((*it)->P );

	// CForm
	Phase	("CFORM: collision model...");
	Status	("Items to process: %d", cfFaces->size());
	p_total = 0;
	p_cost  = 1.f/(cfFaces->size());

	// Collect faces
	CDB::CollectorPacked CL	(BB,cfVertices->size(),cfFaces->size());
	for (vecFaceIt F = cfFaces->begin(); F!=cfFaces->end(); F++)
	{
		Face*	T = *F;

		TestEdge	(T->v[0],T->v[1],T);
		TestEdge	(T->v[1],T->v[2],T);
		TestEdge	(T->v[2],T->v[0],T);

		CL.add_face	(
			T->v[0]->P, T->v[1]->P, T->v[2]->P,
			T->dwMaterialGame, materials()[T->dwMaterial].sector, T->sm_group
			);
		Progress(p_total+=p_cost);		// progress
	}
	if (bCriticalErrCnt) {
		err_save	();
		clMsg		("MultipleEdges: %d faces",bCriticalErrCnt);
	}
	xr_delete		(cfFaces);
	xr_delete		(cfVertices);

	// Models
	Status			("Models...");
	for (u32 ref=0; ref<mu_refs().size(); ref++)
		mu_refs()[ref]->export_cform_game(CL);

	// Simplification
	if (g_params().m_quality!=ebqDraft)
		SimplifyCFORM	(CL);

	// bb?
	BB.invalidate	();
	for (size_t it = 0; it<CL.getVS(); it++)
		BB.modify( CL.getV()[it] );

	// Saving
	string_path		fn;
	IWriter*		MFS	= FS.w_open	(strconcat(sizeof(fn),fn,pBuild->path,"level.cform"));
	Status			("Saving...");

	// Header
	hdrCFORM hdr;
	hdr.version		= CFORM_CURRENT_VERSION;
	hdr.vertcount	= (u32)CL.getVS();
	hdr.facecount	= (u32)CL.getTS();
	hdr.aabb		= BB;
	MFS->w			(&hdr,sizeof(hdr));

	// Data
	MFS->w			(CL.getV(),(u32)CL.getVS()*sizeof(Fvector));
	MFS->w			(CL.getT(),(u32)CL.getTS()*sizeof(CDB::TRI));

	// Clear pDeflector (it is stored in the same memory space with dwMaterialGame)
	for (vecFaceIt I=lc_global_data()->g_faces().begin(); I!=lc_global_data()->g_faces().end(); I++)
	{
		Face* F			= *I;
		F->pDeflector	= NULL;
	}

	FS.w_close		(MFS);
}
Example #5
0
void	CBuild::BuildCForm	()
{
	Phase			("CFORM: construction...");
	//Status		("Building base mesh : vertices...");

	_mesh			mesh;						// a mesh object
	_decimater		decimater(mesh);			// a decimater object, connected to a mesh
	_HModQuadric	hModQuadric;				// use a quadric module
	decimater.add	(hModQuadric);				// register module at the decimater
	decimater.module(hModQuadric).set_max_err	(0.0001,false);	// error-limit 0.0001

	// Initializing mesh
	Status			("Building base mesh : vertices[%d]...",g_vertices.size());
	for (vecVertexIt _v=g_vertices.begin(); _v!=g_vertices.end(); _v++)	(*_v)->handle	= _mesh::InvalidVertexHandle.idx();

	Status			("Building base mesh : base faces[%d]...",g_faces.size());
	std::vector <_mesh::VertexHandle>	fhandles;
	xr_vector	<cform_FailFace>		failedfaces;
	cform_mergeprops					fmergeprops;

	for (vecFaceIt I=g_faces.begin(); I!=g_faces.end(); I++)
	{
		Progress	(float(I-g_faces.begin())/float(g_faces.size()));
		Face* F		= *I;
		if (F->Shader().flags.bCollision) 
		{
			// test correctness
			TestEdge	(F->v[0],F->v[1],F);
			TestEdge	(F->v[1],F->v[2],F);
			TestEdge	(F->v[2],F->v[0],F);

			// add vertices
			fhandles.clear	();
			for (u32 v=0; v<3; v++)
			{
				_mesh::VertexHandle	h	= _mesh::VertexHandle(F->v[v]->handle);
				if (_mesh::InvalidVertexHandle == h)	{ 
					Fvector& p			= F->v[v]->P; 
					h					= mesh.add_vertex	(_mesh::Point(p.x,p.y,p.z));
					F->v[v]->handle		= h.idx();
				}
				fhandles.push_back	(h);
			}

			// add face
			fmergeprops.material		= F->dwMaterialGame;
			fmergeprops.sector			= materials[F->dwMaterial].sector;
			_mesh::FaceHandle	hface	= mesh.add_face		(fhandles);
			if (hface == _mesh::InvalidFaceHandle)	{
				failedfaces.push_back		(cform_FailFace());
				failedfaces.back().P[0]		= F->v[0]->P;
				failedfaces.back().P[1]		= F->v[1]->P;
				failedfaces.back().P[2]		= F->v[2]->P;
				failedfaces.back().props	= fmergeprops.props;
			}
			else				mesh.face(hface).set_props	(fmergeprops.props);
		}
	}
	if (bCriticalErrCnt) {
		err_save	();
		clMsg		("MultipleEdges: %d faces",bCriticalErrCnt);
	}

	Status			("Building base mesh : models[%d]...",mu_refs.size());
	mesh.garbage_collection		();
	for (u32 ref=0; ref<mu_refs.size(); ref++)
		mu_refs[ref]->export_cform_game(mesh,failedfaces);

	Status			("Building base mesh : normals...");
	mesh.garbage_collection		();
	mesh.request_vertex_normals	();
	mesh.update_vertex_normals	();

	// Decimate
	Status			("Reconstructing mesh-topology...");
	clMsg			("%d faces failed topology check",	failedfaces.size());
	clMsg			("%f%% geometry/artist quality",	100.f * (1-float(failedfaces.size())/float(mesh.n_faces())));

	decimater.initialize	();      // let the decimater initialize the mesh and the modules

	int		nf_before		= int	(mesh.n_faces());
	int		nv_before		= int	(mesh.n_vertices());
	int		nc				= decimater.decimate	(nv_before);	// do decimation, as large, as possible
							mesh.garbage_collection	();
	int		nf_after		= int	(mesh.n_faces());
	int		nv_after		= int	(mesh.n_vertices());
	clMsg					("vertices: was[%d], now[%d] => %f %% left",nv_before,nv_after, 100.f*float(nv_after)/float(nv_before) );
	clMsg					("   faces: was[%d], now[%d] => %f %% left",nf_before,nf_after, 100.f*float(nf_after)/float(nf_before) );

	// Decimate
	Status			("Refactoring CFORM...");
	Fbox BB;	BB.invalidate();
	_mesh::VertexIter	vit	=mesh.vertices_begin(),vend=mesh.vertices_end();
	for (; vit!=vend; ++vit)
		BB.modify( reinterpret_cast<Fvector&>(mesh.point(vit)) );

	CDB::CollectorPacked	CL(BB,mesh.n_vertices(),mesh.n_faces());
	_mesh::FaceIter			fit=mesh.faces_begin(),fend=mesh.faces_end();
	for (; fit!=fend; ++fit){
		// get vertex-handles
		fhandles.clear	();
		for (_mesh::CFVIter fv_it=mesh.cfv_iter(fit); fv_it; ++fv_it)
			fhandles.push_back	(fv_it.handle());
		CL.add_face_D	(
			reinterpret_cast<Fvector&>(mesh.point	(fhandles[0])),
			reinterpret_cast<Fvector&>(mesh.point	(fhandles[1])),
			reinterpret_cast<Fvector&>(mesh.point	(fhandles[2])),
			fit->props	()
			);
	}
	Status			("Restoring fail-faces...");
	for (u32 it=0; it<failedfaces.size(); it++)		{
		cform_FailFace&	F	= failedfaces[it];
		CL.add_face_D		( F.P[0], F.P[1], F.P[2], F.props );
	}

	// Saving
	Status			("Saving...");
			nf_after		= int	(CL.getTS());
			nv_after		= int	(CL.getVS());
	clMsg					("vertices: was[%d], now[%d] => %f %% left",nv_before,nv_after, 100.f*float(nv_after)/float(nv_before) );
	clMsg					("   faces: was[%d], now[%d] => %f %% left",nf_before,nf_after, 100.f*float(nf_after)/float(nf_before) );
	string512		fn;
	IWriter*		MFS	= FS.w_open	(strconcat(fn,pBuild->path,"level.cform"));
	
	// Header
	hdrCFORM		hdr;
	hdr.version		= CFORM_CURRENT_VERSION;
	hdr.vertcount	= (u32)CL.getVS();
	hdr.facecount	= (u32)CL.getTS();
	hdr.aabb		= BB;
	MFS->w			(&hdr,sizeof(hdr));
	// Data
	MFS->w			(CL.getV(),(u32)CL.getVS()*sizeof(Fvector));
	MFS->w			(CL.getT(),(u32)CL.getTS()*sizeof(CDB::TRI));
	// Clear pDeflector (it is stored in the same memory space with dwMaterialGame)
	for (vecFaceIt I=g_faces.begin(); I!=g_faces.end(); I++)	{
		Face* F			= *I;
		F->pDeflector	= NULL;
	}
	FS.w_close		(MFS);
}