@woosh/meep-engine
Version:
Pure JavaScript game engine. Fully featured and production ready.
154 lines (116 loc) • 5.25 kB
JavaScript
//
import { v3_dot } from "../../../../../../core/geom/vec3/v3_dot.js";
import { v3_length } from "../../../../../../core/geom/vec3/v3_length.js";
/**
*
* @param {StreamGeometryBuilder} out
* @param {number} Px
* @param {number} Py
* @param {number} Pz
* @param {Vector3} N normal
* @param {Vector3} B binormal
* @param {Vector3} T tangent
* @param {number} u X component of UV
* @param {number[]|Float32Array} bend_angle
* @param {number[]|Float32Array} shape 2d shape, format [x0,y1, x1,y1, ... , xN,yN]
* @param {number[]|Float32Array} shape_normals
* @param {number} shape_length number of points in the shape
* @param {number[]|Float32Array} shape_transform 3x3 2d transform matrix for shape Note that matrix uses row-major order
*/
export function make_ring_vertices(
out,
Px, Py, Pz,
N, B, T,
u, bend_angle,
shape, shape_normals, shape_length,
shape_transform
) {
const out_positions = out.positions;
const out_normals = out.normals;
const out_uvs = out.uvs;
for (let i = 0; i <= shape_length; i++) {
const j = i % shape_length;
const i2 = j * 2;
const shape_x = shape[i2];
const shape_y = shape[i2 + 1];
// apply transform to the shape
const tx = shape_transform[0] * shape_x + shape_transform[3] * shape_y + shape_transform[6];
const ty = shape_transform[1] * shape_x + shape_transform[4] * shape_y + shape_transform[7];
const b_sin_x = ty * N.x;
const b_sin_y = ty * N.y;
const b_sin_z = ty * N.z;
const n_cos_x = tx * B.x;
const n_cos_y = tx * B.y;
const n_cos_z = tx * B.z;
// compute radial normal
const radial_normal_x_raw = (n_cos_x - b_sin_x);
const radial_normal_y_raw = (n_cos_y - b_sin_y);
const radial_normal_z_raw = (n_cos_z - b_sin_z);
const radial_normal_magnitude = v3_length(radial_normal_x_raw, radial_normal_y_raw, radial_normal_z_raw);
let normal_x;
let normal_y;
let normal_z;
if (radial_normal_magnitude !== 0) {
const normalization_factor = 1 / radial_normal_magnitude;
// re-normalize and compensate by bending angle
normal_x = radial_normal_x_raw * normalization_factor;
normal_y = radial_normal_y_raw * normalization_factor;
normal_z = radial_normal_z_raw * normalization_factor;
} else {
// normal would be 0 and produce NaNs, apply arbitrary offset
normal_x = T.x;
normal_y = T.y;
normal_z = T.z;
}
const shape_normal_x = shape_normals[i2];
const shape_normal_y = shape_normals[i2 + 1];
const t_nx = shape_transform[0] * shape_normal_x + shape_transform[3] * shape_normal_y + shape_transform[6];
const t_ny = shape_transform[1] * shape_normal_x + shape_transform[4] * shape_normal_y + shape_transform[7];
const nb_sin_x = t_ny * N.x;
const nb_sin_y = t_ny * N.y;
const nb_sin_z = t_ny * N.z;
const nn_cos_x = t_nx * B.x;
const nn_cos_y = t_nx * B.y;
const nn_cos_z = t_nx * B.z;
const n_normal_x_raw = (-nn_cos_x - nb_sin_x);
const n_normal_y_raw = (-nn_cos_y - nb_sin_y);
const n_normal_z_raw = (-nn_cos_z - nb_sin_z);
const n_normal_magnitude = v3_length(n_normal_x_raw, n_normal_y_raw, n_normal_z_raw);
const cv = out.cursor_vertices;
const cv3 = cv * 3;
if (n_normal_magnitude !== 0) {
out_normals[cv3] = n_normal_x_raw / n_normal_magnitude;
out_normals[cv3 + 1] = n_normal_y_raw / n_normal_magnitude;
out_normals[cv3 + 2] = n_normal_z_raw / n_normal_magnitude;
} else {
out_normals[cv3] = T.x;
out_normals[cv3 + 1] = T.y;
out_normals[cv3 + 2] = T.z;
}
let bend_magnitude = 1;
// rotate bend normal by 90deg
const cross_x = bend_angle[1] * T.z - bend_angle[2] * T.y;
const cross_y = bend_angle[2] * T.x - bend_angle[0] * T.z;
const cross_z = bend_angle[0] * T.y - bend_angle[1] * T.x;
const rotated_bend_normal_length = v3_length(cross_x, cross_y, cross_z);
const bend_normal_length_inv = 1 / rotated_bend_normal_length;
// apply bend angle
const dot = v3_dot(
cross_x * bend_normal_length_inv, cross_y * bend_normal_length_inv, cross_z * bend_normal_length_inv,
normal_x, normal_y, normal_z
);
bend_magnitude += Math.abs(dot) * bend_angle[3];
// compute vertex position
const vx = Px + radial_normal_x_raw * bend_magnitude;
const vy = Py + radial_normal_y_raw * bend_magnitude;
const vz = Pz + radial_normal_z_raw * bend_magnitude;
out_positions[cv3] = vx;
out_positions[cv3 + 1] = vy;
out_positions[cv3 + 2] = vz;
// UV
const cv2 = cv * 2;
out_uvs[cv2] = u;
out_uvs[cv2 + 1] = i / shape_length;
out.cursor_vertices++;
}
}