Ejemplo n.º 1
0
/*
 * given a triangle a,b,c, create 4 triangles:
 *
 *                  a
 *                 / \
 *                /   \
 *              d-------e
 *              /\     /\
 *             /  \   /  \
 *            /    \ /    \
 *           /      \      \
 *          b-------f-------c
 *
 * a,d,e, e,d,f, d,b,f, and e,f,c
 *
 */
static void subdivide_triangle(struct mesh *m, int tri)
{
	struct vertex d, e, f, *pa, *pb, *pc, *pd, *pe, *pf;
	union vec3 vd, ve, vf;
	int shared, t;

	pa = m->t[tri].v[0];
	pb = m->t[tri].v[1];
	pc = m->t[tri].v[2];

	vd.v.x = (pa->x + pb->x) / 2.0;
	vd.v.y = (pa->y + pb->y) / 2.0;
	vd.v.z = (pa->z + pb->z) / 2.0;
	ve.v.x = (pa->x + pc->x) / 2.0;
	ve.v.y = (pa->y + pc->y) / 2.0;
	ve.v.z = (pa->z + pc->z) / 2.0;
	vf.v.x = (pb->x + pc->x) / 2.0;
	vf.v.y = (pb->y + pc->y) / 2.0;
	vf.v.z = (pb->z + pc->z) / 2.0;

	vec3_normalize_self(&vd);
	vec3_normalize_self(&ve);
	vec3_normalize_self(&vf);

	d.x = vd.v.x;
	d.y = vd.v.y;
	d.z = vd.v.z;
	e.x = ve.v.x;
	e.y = ve.v.y;
	e.z = ve.v.z;
	f.x = vf.v.x;
	f.y = vf.v.y;
	f.z = vf.v.z;

	pd = lookup_maybe_add_vertex(m, &d, &shared);
	pe = lookup_maybe_add_vertex(m, &e, &shared);
	pf = lookup_maybe_add_vertex(m, &f, &shared);

	/* replace initial triangle with central triangle, e,d,f */
	m->t[tri].v[0] = pe;
	m->t[tri].v[1] = pd;
	m->t[tri].v[2] = pf;

	/* add 3 surrounding triangles  a,d,e, d,b,f, and e,f,c */
	t = m->ntriangles;
	m->t[t].v[0] = pa;
	m->t[t].v[1] = pd;
	m->t[t].v[2] = pe;
	t++;
	m->t[t].v[0] = pd;
	m->t[t].v[1] = pb;
	m->t[t].v[2] = pf;
	t++;
	m->t[t].v[0] = pe;
	m->t[t].v[1] = pf;
	m->t[t].v[2] = pc;
	t++;
	m->ntriangles = t;
}
Ejemplo n.º 2
0
/* For the +z face of a cubemapped unit sphere, returns tangent and bitangent vectors
 * See: http://www.iquilezles.org/www/articles/patchedsphere/patchedsphere.htm
 */
void cubemapped_sphere_tangent_and_bitangent(float x, float y, union vec3 *u, union vec3 *v)
{
	u->v.x = -(1.0f + y * y);
	u->v.y = x * y;
	u->v.z = x;
	vec3_normalize_self(u);

	v->v.x = x * y;
	v->v.y = -(1 + x * x);
	v->v.z = y;
	vec3_normalize_self(v);
}
Ejemplo n.º 3
0
/* for a plane defined by n=normal, return a u and v vector that is on that plane and perpendictular */
void plane_vector_u_and_v_from_normal(union vec3 *u, union vec3 *v, const union vec3 *n)
{
	union vec3 basis = { { 1, 0, 0 } };

	/* find a vector we can use for our basis to define v */
	float dot = vec3_dot(n, &basis);
	if (fabs(dot) >= 1.0 - ZERO_TOLERANCE) {
		/* if forward is parallel, we can use up */
		vec3_init(&basis, 0, 1, 0);
	}

	/* find the right vector from our basis and the normal */
	vec3_cross(v, &basis, n);
	vec3_normalize_self(v);

	/* now the final forward vector is perpendicular n and v */
	vec3_cross(u, n, v);
	vec3_normalize_self(u);
}
Ejemplo n.º 4
0
static void normalize_sphere(struct mesh *m)
{
	int i;

	for (i = 0; i < m->nvertices; i++) {
		union vec3 v = { { m->v[i].x, m->v[i].y, m->v[i].z } };
		vec3_normalize_self(&v);
		m->v[i].x = v.v.x;
		m->v[i].y = v.v.y;
		m->v[i].y = v.v.y;
	}
	m->radius = 1.0;
}
Ejemplo n.º 5
0
static void recursive_add_bump(union vec3 pos, float r, float h,
				float shrink, float rlimit)
{
	float hoffset;

	add_bump(pos, r, h);
	if (r * shrink < rlimit)
		return;
	for (int i = 0; i < nbumps; i++) {
		union vec3 d;
		d.v.x = snis_random_float() * r * scatterfactor;
		d.v.y = snis_random_float() * r * scatterfactor;
		d.v.z = snis_random_float() * r * scatterfactor;
		vec3_add_self(&d, &pos);
		vec3_normalize_self(&d);
		hoffset = snis_random_float() * h * shrink * 0.5;
		recursive_add_bump(d, r * shrink, h * (shrink + 0.5 * (1.0 - shrink)) + hoffset, shrink, rlimit);
	}
}
Ejemplo n.º 6
0
void mesh_set_spherical_vertex_normals(struct mesh *m)
{
	int i, j;

	for (i = 0; i < m->ntriangles; i++) {
		union vec3 normal;
		normal = compute_triangle_normal(&m->t[i]);
		m->t[i].n.x = normal.v.x;
		m->t[i].n.y = normal.v.y;
		m->t[i].n.z = normal.v.z;
		for (j = 0; j < 3; j++) {
			union vec3 normal = { { m->t[i].v[j]->x, m->t[i].v[j]->y, m->t[i].v[j]->z } };
			vec3_normalize_self(&normal);
			m->t[i].vnormal[j].x = normal.v.x;
			m->t[i].vnormal[j].y = normal.v.y;
			m->t[i].vnormal[j].z = normal.v.z;
		}
	}
}
Ejemplo n.º 7
0
static union vec3 compute_triangle_normal(struct triangle *t)
{
	union vec3 v1, v2, cross;

	v1.v.x = t->v[1]->x - t->v[0]->x;
	v1.v.y = t->v[1]->y - t->v[0]->y;
	v1.v.z = t->v[1]->z - t->v[0]->z;

	v2.v.x = t->v[2]->x - t->v[1]->x;
	v2.v.y = t->v[2]->y - t->v[1]->y;
	v2.v.z = t->v[2]->z - t->v[1]->z;

	vec3_cross(&cross, &v1, &v2);
	vec3_normalize_self(&cross);

	/* make sure we always have a valid normal */
	if (isnan(cross.v.x) || isnan(cross.v.y) || isnan(cross.v.z))
		vec3_init(&cross, 0, 1, 0);

	return cross;
}
Ejemplo n.º 8
0
/* convert from cubemap coords to cartesian coords on surface of sphere */
static union vec3 fij_to_xyz(int f, int i, int j, const int dim)
{
	union vec3 answer;

	switch (f) {
	case 0:
		answer.v.x = (float) (i - dim / 2) / (float) dim;
		answer.v.y = -(float) (j - dim / 2) / (float) dim;
		answer.v.z = 0.5;
		break;
	case 1:
		answer.v.x = 0.5;
		answer.v.y = -(float) (j - dim / 2) / (float) dim;
		answer.v.z = -(float) (i - dim / 2) / (float) dim;
		break;
	case 2:
		answer.v.x = -(float) (i - dim / 2) / (float) dim;
		answer.v.y = -(float) (j - dim / 2) / (float) dim;
		answer.v.z = -0.5;
		break;
	case 3:
		answer.v.x = -0.5;
		answer.v.y = -(float) (j - dim / 2) / (float) dim;
		answer.v.z = (float) (i - dim / 2) / (float) dim;
		break;
	case 4:
		answer.v.x = (float) (i - dim / 2) / (float) dim;
		answer.v.y = 0.5;
		answer.v.z = (float) (j - dim / 2) / (float) dim;
		break;
	case 5:
		answer.v.x = (float) (i - dim / 2) / (float) dim;
		answer.v.y = -0.5;
		answer.v.z = -(float) (j - dim / 2) / (float) dim;
		break;
	}
	vec3_normalize_self(&answer);
	return answer;
}
Ejemplo n.º 9
0
/* fabricate a tube of length h, radius r, with nfaces, parallel to x axis */
struct mesh *mesh_tube(float h, float r, float nfaces)
{
	struct mesh *m;
	int ntris = nfaces * 2;
	int nvertices = nfaces * 2;
	int i, j;
	float angle, da;

	float l = h / 2.0;

	m = allocate_mesh_for_copy(ntris, nvertices, 0, 1);
	if (!m)
		return m;

	m->geometry_mode = MESH_GEOMETRY_TRIANGLES;
	da = 2 * M_PI / (float) nfaces;
	angle = 0.0;
	for (i = 0; i < nvertices; i += 2) {
		m->v[i].x = -l;
		m->v[i].y = r * cos(angle);
		m->v[i].z = r * -sin(angle);
		m->v[i + 1].x = l;
		m->v[i + 1].y = m->v[i].y;
		m->v[i + 1].z = m->v[i].z;
		angle += da;
	}
	m->nvertices = nvertices;

	for (i = 0; i < ntris; i += 2) {
		m->t[i].v[2] = &m->v[i % nvertices];
		m->t[i].v[1] = &m->v[(i + 1) % nvertices];
		m->t[i].v[0] = &m->v[(i + 2) % nvertices];

		m->t[i + 1].v[2] = &m->v[(i + 2) % nvertices];
		m->t[i + 1].v[1] = &m->v[(i + 1) % nvertices];
		m->t[i + 1].v[0] = &m->v[(i + 3) % nvertices];
	}
	m->ntriangles = ntris;

	for (i = 0; i < ntris; i++) {
		union vec3 normal;
		normal = compute_triangle_normal(&m->t[i]);
		m->t[i].n.x = normal.v.x;
		m->t[i].n.y = normal.v.y;
		m->t[i].n.z = normal.v.z;
		for (j = 0; j < 3; j++) {
			union vec3 normal = { { 0, -m->t[i].v[j]->y, -m->t[i].v[j]->z } };
			vec3_normalize_self(&normal);
			m->t[i].vnormal[j].x = normal.v.x;
			m->t[i].vnormal[j].y = normal.v.y;
			m->t[i].vnormal[j].z = normal.v.z;
		}
	}
	mesh_set_flat_shading_vertex_normals(m);
	for (i = 0; i < ntris; i += 2) {
		mesh_set_triangle_texture_coords(m, i,
			0.0, (float) ((int) ((i + 2) / 2)) * 1.0 / (float) nfaces,
			1.0, (float) ((int) (i / 2)) / (float) nfaces,
			0.0, (float) ((int) (i / 2)) / (float) nfaces);
		mesh_set_triangle_texture_coords(m, i + 1,
			1.0, (float) ((int) ((i + 2) / 2)) / (float) nfaces,
			1.0, (float) ((int) (i / 2)) / (float) nfaces,
			0.0, (float) ((int) ((i + 2) / 2)) / (float) nfaces);
	}
	m->nlines = 0;
	m->radius = mesh_compute_radius(m);
	mesh_graph_dev_init(m);
	return m;
}