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.