Skip to content

Instantly share code, notes, and snippets.

@spite
Last active September 2, 2021 16:42
Show Gist options
  • Save spite/7384392c30d50c7ac1d1f504a8a3b40a to your computer and use it in GitHub Desktop.
Save spite/7384392c30d50c7ac1d1f504a8a3b40a to your computer and use it in GitHub Desktop.
distorts an icosahedron sphere into a superellipsoid
// https://en.wikipedia.org/wiki/Superellipsoid
function c(w, m) {
const cv = Math.cos(w);
return Math.sign(cv) * Math.abs(cv) ** m;
}
function s(w, m) {
const sv = Math.sin(w);
return Math.sign(sv) * Math.abs(sv) ** m;
}
function getSuperEllipsoidPoint(theta, phi) {
// radii
const A = 1;
const B = 1;
const C = 1;
// https://en.wikipedia.org/wiki/Superellipsoid#/media/File:Superellipsoid_collection.png
// r = 2/e, t = 2/n
const r = 4;
const t = 4;
const x = A * c(theta, 2 / t) * c(phi, 2 / r);
const y = B * c(theta, 2 / t) * s(phi, 2 / r);
const z = C * s(theta, 2 / t);
return { x, y, z };
}
const v0 = new Vector3();
const v1 = new Vector3();
const v2 = new Vector3();
function getSuperEllipsoidNormal(theta, phi) {
const e = 0.00001;
const { x: x0, y: y0, z: z0 } = getSuperEllipsoidPoint(theta, phi);
const { x: x1, y: y1, z: z1 } = getSuperEllipsoidPoint(theta + e, phi);
const { x: x2, y: y2, z: z2 } = getSuperEllipsoidPoint(theta, phi + e);
v0.set(x0, y0, z0);
v1.set(x1, y1, z1).sub(v0);
v2.set(x2, y2, z2).sub(v0);
v0.crossVectors(v1, v2);
return { x: v0.x, y: v0.y, z: v0.z };
}
function createSuperEllipsoid() {
const geometry = new IcosahedronBufferGeometry(1, 10);
const vertices = geometry.attributes.position.array;
const normals = geometry.attributes.normal.array;
const v = new Vector3();
for (let i = 0; i < vertices.length; i += 3) {
v.set(vertices[i], vertices[i + 1], vertices[i + 2]);
const theta = Math.atan2(Math.sqrt(v.x ** 2 + v.y ** 2), v.z) + Math.PI / 2;
const phi = Math.atan2(v.y, v.x);
const { x, y, z } = getSuperEllipsoidPoint(theta, phi);
vertices[i] = x;
vertices[i + 1] = y;
vertices[i + 2] = z;
const { x: nx, y: ny, z: nz } = getSuperEllipsoidNormal(theta, phi);
normals[i] = nx;
normals[i + 1] = ny;
normals[i + 2] = nz;
}
return geometry;
}
const geometry2 = createSuperEllipsoid();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment