Skip to content

Instantly share code, notes, and snippets.

@socantre
Last active August 29, 2015 14:07
Show Gist options
  • Save socantre/cadcecc03d67e1434ebb to your computer and use it in GitHub Desktop.
Save socantre/cadcecc03d67e1434ebb to your computer and use it in GitHub Desktop.
(relatively) even tessellation of sphere
void tessellate_sphere(...) {
// tetrahedron
//Point a{ { 1, 1, 1 } }, b{ { 1,-1, -1 } }, c{ { -1, 1, -1 } }, d{ { -1, -1, 1 } };
//std::vector<Triangle> tris = {
// { { a, b, c } },
// { { a, c, d } },
// { { a, d, b } },
// { { b, d, c } }
//};
// octohedron
//Point a{ { 1, 0, 0 } }, b{ { -1, 0, 0 } }, c{ { 0, 1, 0 } }, d{ { 0, -1, 0 } }, e{ { 0, 0, 1 } }, f{{ 0, 0, -1 }};
//std::vector<Triangle> tris = {
// { { a, f, c } },
// { { a, c, e } },
// { { a, e, d } },
// { { a, d, f } },
// { { b, c, f } },
// { { b, f, d } },
// { { b, d, e } },
// { { b, e, c } }
//};
// icosahedron
const float phi = 1.61803398875;
Point p[12] = {
{ { 0, 1, phi } },
{ { 0, 1, -phi } },
{ { 0, -1, phi } },
{ { 0, -1, -phi } },
{ { 1, phi, 0 } },
{ { 1, -phi, 0 } },
{ { -1, phi, 0 } },
{ { -1, -phi, 0 } },
{ { phi, 0, 1 } },
{ { -phi, 0, 1 } },
{ { phi, 0, -1 } },
{ { -phi, 0, -1 } },
};
std::vector<Triangle> tris = {
{ { p[0], p[2], p[8] } },
{ { p[0], p[8], p[4] } },
{ { p[0], p[4], p[6] } },
{ { p[0], p[6], p[9] } },
{ { p[0], p[9], p[2] } },
{ { p[1], p[3], p[10] } },
{ { p[1], p[10], p[4] } },
{ { p[1], p[4], p[6] } },
{ { p[1], p[6], p[11] } },
{ { p[1], p[11], p[3] } },
{ { p[2], p[9], p[7] } },
{ { p[2], p[7], p[5] } },
{ { p[2], p[5], p[8] } },
{ { p[3], p[11], p[7] } },
{ { p[3], p[7], p[5] } },
{ { p[3], p[5], p[10] } },
{ { p[4], p[8], p[10] } },
{ { p[5], p[8], p[10] } },
{ { p[6], p[11], p[9] } },
{ { p[7], p[9], p[11] } }
};
for (int i = 0; i < 5; ++i) {
tris = split_triangles(tris);
}
for (auto &&t : tris) {
for (auto &&p : t.v) {
p.normalize();
}
}
for (auto &&t: tris) {
add_triangle(t); // coordinates double as vertex normals
}
}
struct Point {
float coords[3];
Point &operator+=(Point const &rhs) {
for (int i = 0; i < 3; ++i) {
coords[i] += rhs.coords[i];
}
return *this;
}
Point &operator/=(float rhs) {
for (int i = 0; i < 3; ++i) {
coords[i] /= rhs;
}
return *this;
}
float abs() {
return std::sqrt(std::inner_product(coords, coords + 3, coords, 0.0f));
}
Point &normalize() {
return *this /= abs();
}
};
Point operator+(Point lhs, Point const &rhs) {
return lhs += rhs;
}
Point operator/(Point lhs, float rhs) {
return lhs /= rhs;
}
struct Triangle {
Point v[3];
};
std::array<Triangle, 4> split_triangle(Triangle const &t) {
return{ {
{ { t.v[0], (t.v[0] + t.v[1]) / 2.f, (t.v[0] + t.v[2]) / 2.f } },
{ { (t.v[0] + t.v[1]) / 2.f, t.v[1], (t.v[1] + t.v[2]) / 2.f } },
{ { (t.v[1] + t.v[2]) / 2.f, t.v[2], (t.v[0] + t.v[2]) / 2.f } },
{ { (t.v[0] + t.v[1]) / 2.f, (t.v[1] + t.v[2]) / 2.f, (t.v[0] + t.v[2]) / 2.f } },
} };
}
std::vector<Triangle> split_triangles(std::vector<Triangle> const &ts) {
std::vector<Triangle> result;
for (Triangle const &t : ts) {
auto split = split_triangle(t);
result.insert(end(result), std::begin(split), std::end(split));
}
assert(result.size() == ts.size() * 4);
return result;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment