Cone

How to 3D

Chapter 3: Meshes

Cone

A cone is a cylinder whose circles of latitude are scaled in proportion to their height. A true cone narrows to fine point at one end. We will allow the bottom and top of the cylinder to have radii of the client's choosing. A tapering cylinder with a non-zero radius at its narrow end is technically a conical frustum. For simplicity, we will call it a cone.

Its generator function accepts two radii parameters:

export class Prefab {
  static cone(topRadius: number, bottomRadius: number, length: number, longitudeCount: number, latitudeCount: number) {
    // ...
  }
}
export class Prefab {
  static cone(topRadius: number, bottomRadius: number, length: number, longitudeCount: number, latitudeCount: number) {
    // ...
  }
}

The code for generating a cone is nearly identical to the code for generating a cylinder. The only difference is the calculation of the radius at each circle of latitude. The bottom circle should use the bottomRadius value, and the top circle should use topRadius. In between, we linearly interpolate between the bottom and top radii.

We've seen how the graphics card performs linear interpolation of out variables in a vertex shader. These prefab generators run in JavaScript on the CPU, which has no builtin interpolation routine. Since we'll need to interpolate frequently, let's write our own lerp function:

export function lerp(a: number, b: number, t: number) {
  // t is a proportion in [0, 1]. It it's 0.2, we
  // take 80% of a and 20% of b.
  return a * (1 - t) + b * t;
}
export function lerp(a: number, b: number, t: number) {
  // t is a proportion in [0, 1]. It it's 0.2, we
  // take 80% of a and 20% of b.
  return a * (1 - t) + b * t;
}

Place this function in a new file named lib/math-utilities.ts.

In cone, compute the radius by calling lerp just inside the outer loop that generates the positions:

export class Prefab {
  static cone(topRadius: number, bottomRadius: number, length: number, longitudeCount: number, latitudeCount: number) {
    const positions: Vector3[] = [];

    for (let lat = 0; lat < latitudeCount; ++lat) {
      const radius = lerp(bottomRadius, topRadius, lat / (latitudeCount - 1));
      // ...
    }

    // ...
  }
}
export class Prefab {
  static cone(topRadius: number, bottomRadius: number, length: number, longitudeCount: number, latitudeCount: number) {
    const positions: Vector3[] = [];

    for (let lat = 0; lat < latitudeCount; ++lat) {
      const radius = lerp(bottomRadius, topRadius, lat / (latitudeCount - 1));
      // ...
    }

    // ...
  }
}

Cylinders and cones roll up the grid along one axis. Let's see how to roll it around two axes to make a sphere.

← CylinderSphere →