How to resolve the algorithm Catmull–Clark subdivision surface step by step in the C programming language

Published on 7 June 2024 03:52 AM
#C

How to resolve the algorithm Catmull–Clark subdivision surface step by step in the C programming language

Table of Contents

Problem Statement

Implement the Catmull-Clark surface subdivision (description on Wikipedia), which is an algorithm that maps from a surface (described as a set of points and a set of polygons with vertices at those points) to another more refined surface. The resulting surface will always consist of a mesh of quadrilaterals. The process for computing the new locations of the points works as follows when the surface is free of holes: Then each face is replaced by new faces made with the new points, When there is a hole, we can detect it as follows: On the border of a hole the subdivision occurs as follows: For edges and vertices not next to a hole, the standard algorithm from above is used.

Let's start with the solution:

Step by Step solution about How to resolve the algorithm Catmull–Clark subdivision surface step by step in the C programming language

The provided C code implements the Catmull-Clark subdivision algorithm, which is a method for creating smoother surfaces from a given polygonal mesh. Here's a detailed explanation of its functionality:

face_point(face f):

  • This function takes a face f as input and returns a vertex representing the face's center point.
  • It calculates the average position of all the face's vertices and stores it in the face's avg field.
  • If the face's avg field is not set, it initializes a new vertex, calculates the average position, and stores it in f->avg.

edge_point(edge e):

  • This function takes an edge e as input and returns a vertex representing the edge's midpoint.
  • It calculates the average position of the edge's two vertices and stores it in e->avg.
  • If the edge is not on a hole (meaning it has two adjacent faces), it also computes the average of the face centers connected to the edge and adds them to the midpoint position.
  • It stores the computed midpoint in the edge's e_pt field.

updated_point(vertex v):

  • This function takes a vertex v as input and returns a new vertex representing its updated position after subdivision.
  • It calculates the updated vertex position based on the following conditions:
    • If v is on a hole (i.e., not all adjacent edges are faces), it computes the average of the midpoints of the hole edges and the vertex's original position.
    • If v is not on a hole, it computes the average of the face centers and the midpoints of the adjacent edges, taking into account the number of faces and edges connected to the vertex.
  • The computed updated position is stored in the vertex's v_new field.

catmull(model m):

  • This function applies the Catmull-Clark subdivision algorithm to the input model m.

  • It iterates over the faces in m and creates new faces for the subdivided surface.

  • For each face, it creates four new faces:

    • One face using the updated positions of the face's four vertices as corners.
    • Three additional faces using the edge midpoints, the face center point, and the updated vertex position as corners.
  • The newly created faces are added to the resulting model nm.

  • Finally, the function returns the subdivided model nm.

In summary, this code performs Catmull-Clark subdivision on a polygonal mesh, resulting in a smoother surface by creating new vertices and faces.

Source code in the c programming language

vertex face_point(face f)
{
	int i;
	vertex v;

	if (!f->avg) {
		f->avg = vertex_new();
		foreach(i, v, f->v)
			if (!i) f->avg->pos = v->pos;
			else    vadd(f->avg->pos, v->pos);

		vdiv(f->avg->pos, len(f->v));
	}
	return f->avg;
}

#define hole_edge(e) (len(e->f)==1)
vertex edge_point(edge e)
{
	int i;
	face f;

	if (!e->e_pt) {
		e->e_pt = vertex_new();
		e->avg = e->v[0]->pos;
		vadd(e->avg, e->v[1]->pos);
		e->e_pt->pos = e->avg;

		if (!hole_edge(e)) {
			foreach (i, f, e->f)
				vadd(e->e_pt->pos, face_point(f)->pos);
			vdiv(e->e_pt->pos, 4);
		} else
			vdiv(e->e_pt->pos, 2);

		vdiv(e->avg, 2);
	}

	return e->e_pt;
}

#define hole_vertex(v) (len((v)->f) != len((v)->e))
vertex updated_point(vertex v)
{
	int i, n = 0;
	edge e;
	face f;
	coord_t sum = {0, 0, 0};

	if (v->v_new) return v->v_new;

	v->v_new = vertex_new();
	if (hole_vertex(v)) {
		v->v_new->pos = v->pos;
		foreach(i, e, v->e) {
			if (!hole_edge(e)) continue;
			vadd(v->v_new->pos, edge_point(e)->pos);
			n++;
		}
		vdiv(v->v_new->pos, n + 1);
	} else {
		n = len(v->f);
		foreach(i, f, v->f)
			vadd(sum, face_point(f)->pos);
		foreach(i, e, v->e)
			vmadd(sum, edge_point(e)->pos, 2, sum);
		vdiv(sum, n);
		vmadd(sum, v->pos, n - 3, sum);
		vdiv(sum, n);
		v->v_new->pos = sum;
	}

	return v->v_new;
}

model catmull(model m)
{
	int i, j, a, b, c, d;
	face f;
	vertex v, x;

	model nm = model_new();
	foreach (i, f, m->f) {
		foreach(j, v, f->v) {
			_get_idx(a, updated_point(v));
			_get_idx(b, edge_point(elem(f->e, (j + 1) % len(f->e))));
			_get_idx(c, face_point(f));
			_get_idx(d, edge_point(elem(f->e, j)));
			model_add_face(nm, 4, a, b, c, d);
		}
	}
	return nm;
}


  

You may also check:How to resolve the algorithm Pascal matrix generation step by step in the PARI/GP programming language
You may also check:How to resolve the algorithm Table creation/Postal addresses step by step in the C programming language
You may also check:How to resolve the algorithm A+B step by step in the FBSL programming language
You may also check:How to resolve the algorithm Kaprekar numbers step by step in the Phix programming language
You may also check:How to resolve the algorithm Reverse words in a string step by step in the Nanoquery programming language