UNPKG

@woosh/meep-engine

Version:

Pure JavaScript game engine. Fully featured and production ready.

154 lines (116 loc) 5.25 kB
// 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++; } }