three-stdlib
Version:
stand-alone library of threejs examples
125 lines (124 loc) • 4.59 kB
JavaScript
import { BufferAttribute, DynamicDrawUsage, BufferGeometry, MeshStandardMaterial, Mesh, Vector3, Color, Matrix4 } from "three";
function TubePainter() {
const BUFFER_SIZE = 1e6 * 3;
const positions = new BufferAttribute(new Float32Array(BUFFER_SIZE), 3);
positions.usage = DynamicDrawUsage;
const normals = new BufferAttribute(new Float32Array(BUFFER_SIZE), 3);
normals.usage = DynamicDrawUsage;
const colors = new BufferAttribute(new Float32Array(BUFFER_SIZE), 3);
colors.usage = DynamicDrawUsage;
const geometry = new BufferGeometry();
geometry.setAttribute("position", positions);
geometry.setAttribute("normal", normals);
geometry.setAttribute("color", colors);
geometry.drawRange.count = 0;
const material = new MeshStandardMaterial({
vertexColors: true
});
const mesh = new Mesh(geometry, material);
mesh.frustumCulled = false;
function getPoints(size2) {
const PI2 = Math.PI * 2;
const sides = 10;
const array = [];
const radius = 0.01 * size2;
for (let i = 0; i < sides; i++) {
const angle = i / sides * PI2;
array.push(new Vector3(Math.sin(angle) * radius, Math.cos(angle) * radius, 0));
}
return array;
}
const vector1 = new Vector3();
const vector2 = new Vector3();
const vector3 = new Vector3();
const vector4 = new Vector3();
const color = new Color(16777215);
let size = 1;
function stroke(position1, position2, matrix12, matrix22) {
if (position1.distanceToSquared(position2) === 0)
return;
let count2 = geometry.drawRange.count;
const points = getPoints(size);
for (let i = 0, il = points.length; i < il; i++) {
const vertex1 = points[i];
const vertex2 = points[(i + 1) % il];
vector1.copy(vertex1).applyMatrix4(matrix22).add(position2);
vector2.copy(vertex2).applyMatrix4(matrix22).add(position2);
vector3.copy(vertex2).applyMatrix4(matrix12).add(position1);
vector4.copy(vertex1).applyMatrix4(matrix12).add(position1);
vector1.toArray(positions.array, (count2 + 0) * 3);
vector2.toArray(positions.array, (count2 + 1) * 3);
vector4.toArray(positions.array, (count2 + 2) * 3);
vector2.toArray(positions.array, (count2 + 3) * 3);
vector3.toArray(positions.array, (count2 + 4) * 3);
vector4.toArray(positions.array, (count2 + 5) * 3);
vector1.copy(vertex1).applyMatrix4(matrix22).normalize();
vector2.copy(vertex2).applyMatrix4(matrix22).normalize();
vector3.copy(vertex2).applyMatrix4(matrix12).normalize();
vector4.copy(vertex1).applyMatrix4(matrix12).normalize();
vector1.toArray(normals.array, (count2 + 0) * 3);
vector2.toArray(normals.array, (count2 + 1) * 3);
vector4.toArray(normals.array, (count2 + 2) * 3);
vector2.toArray(normals.array, (count2 + 3) * 3);
vector3.toArray(normals.array, (count2 + 4) * 3);
vector4.toArray(normals.array, (count2 + 5) * 3);
color.toArray(colors.array, (count2 + 0) * 3);
color.toArray(colors.array, (count2 + 1) * 3);
color.toArray(colors.array, (count2 + 2) * 3);
color.toArray(colors.array, (count2 + 3) * 3);
color.toArray(colors.array, (count2 + 4) * 3);
color.toArray(colors.array, (count2 + 5) * 3);
count2 += 6;
}
geometry.drawRange.count = count2;
}
const up = new Vector3(0, 1, 0);
const point1 = new Vector3();
const point2 = new Vector3();
const matrix1 = new Matrix4();
const matrix2 = new Matrix4();
function moveTo(position) {
point1.copy(position);
matrix1.lookAt(point2, point1, up);
point2.copy(position);
matrix2.copy(matrix1);
}
function lineTo(position) {
point1.copy(position);
matrix1.lookAt(point2, point1, up);
stroke(point1, point2, matrix1, matrix2);
point2.copy(point1);
matrix2.copy(matrix1);
}
function setSize(value) {
size = value;
}
let count = 0;
function update() {
const start = count;
const end = geometry.drawRange.count;
if (start === end)
return;
positions.updateRange.offset = start * 3;
positions.updateRange.count = (end - start) * 3;
positions.needsUpdate = true;
normals.updateRange.offset = start * 3;
normals.updateRange.count = (end - start) * 3;
normals.needsUpdate = true;
colors.updateRange.offset = start * 3;
colors.updateRange.count = (end - start) * 3;
colors.needsUpdate = true;
count = geometry.drawRange.count;
}
return {
mesh,
moveTo,
lineTo,
setSize,
update
};
}
export {
TubePainter
};
//# sourceMappingURL=TubePainter.js.map