Skip to content

Commit

Permalink
enhance: line use miter joints and arrow gaps.
Browse files Browse the repository at this point in the history
  • Loading branch information
tsengyushiang committed Dec 3, 2024
1 parent af4a81a commit cb15ed3
Showing 1 changed file with 64 additions and 90 deletions.
154 changes: 64 additions & 90 deletions src/three/TraceMesh.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,21 @@ bool isUvBackground(vec2 uv) {
void main() {
vec2 uv = vec2(mod(vUv.x, 1.0), vUv.y);
if (isUvBackground(uv)) {
discard;
if (!isUvBackground(uv) && mod(vUv.x,2.0)<1.0) {
gl_FragColor = vec4(vColor, 1.0);
return;
}
gl_FragColor = vec4(vColor, 1.0);
gl_FragColor = vec4(0.0,0.0,0.0, 0.2);
}
`;

interface Point {
x: number;
y: number;
z: number;
}

export default class TraceMesh extends THREE.Mesh {
constructor() {
const geometry = new THREE.BufferGeometry();
Expand All @@ -58,112 +65,79 @@ export default class TraceMesh extends THREE.Mesh {
this.frustumCulled = false;
}

updateTrace(points: Array<{ x: number; y: number; z: number }>) {
const { attributes } = points.reduce<{
latestPoint: { x: number; y: number; z: number } | undefined;
attributes: {
indices: number[];
vertices: number[];
uvs: number[];
colors: number[];
};
}>(
(prev, point, index) => {
const { attributes, latestPoint } = prev;
if (!latestPoint)
return {
...prev,
latestPoint: point,
};

const prePoint = new THREE.Vector2(latestPoint.x, latestPoint.z);
const curPoint = new THREE.Vector2(point.x, point.z);
const direction = new THREE.Vector2()
.subVectors(curPoint, prePoint)
.normalize();

const thick = 5e-1;
const thickOffset = new THREE.Vector2(
-direction.y,
direction.x
).multiplyScalar(thick / 2);
const uvLength =
new THREE.Vector2().subVectors(curPoint, prePoint).length() / thick;

const point1 = new THREE.Vector2().addVectors(prePoint, thickOffset);
const uv1 = [0, 0];
const point2 = new THREE.Vector2().subVectors(prePoint, thickOffset);
const uv2 = [0, 1];
const point3 = new THREE.Vector2().addVectors(curPoint, thickOffset);
const endUvX =
index === points.length - 1 ? Math.floor(uvLength) : uvLength;
const uv3 = [endUvX, 0];
const point4 = new THREE.Vector2().subVectors(curPoint, thickOffset);
const uv4 = [endUvX, 1];

attributes.vertices.push(
point1.x,
1e-1,
point1.y,
point2.x,
1e-1,
point2.y,
point3.x,
1e-1,
point3.y,
point4.x,
1e-1,
point4.y
);
private computeJointDirection(p0: Point, p1: Point, p2: Point) {
if (!p0) {
const vec = new THREE.Vector2(p2.x - p1.x, p2.z - p1.z);
return new THREE.Vector2(-vec.y, vec.x).normalize();
}
if (!p2) {
const vec = new THREE.Vector2(p1.x - p0.x, p1.z - p0.z);
return new THREE.Vector2(-vec.y, vec.x).normalize();
}

const vec1 = new THREE.Vector2(p1.x - p0.x, p1.z - p0.z).normalize();
const vec2 = new THREE.Vector2(p2.x - p1.x, p2.z - p1.z).normalize();
const vec = new THREE.Vector2().addVectors(vec1, vec2).normalize();
return new THREE.Vector2(-vec.y, vec.x).normalize();
}

updateTrace(points: Array<Point>) {
const indices: number[] = [];
const vertices: number[] = [];
const uvs: number[] = [];
const colors: number[] = [];
let accLength = 0;

for (let pointIndex = 0; pointIndex < points.length; pointIndex++) {
const thick = 5e-1;
const p0 = points[pointIndex - 1];
const p1 = points[pointIndex];
const p2 = points[pointIndex + 1];
const thickOffset = this.computeJointDirection(p0, p1, p2).multiplyScalar(
thick / 2.0
);

const point = new THREE.Vector2(p1.x, p1.z);
const point1 = new THREE.Vector2().addVectors(point, thickOffset);
const point2 = new THREE.Vector2().subVectors(point, thickOffset);
vertices.push(point1.x, 1e-1, point1.y, point2.x, 1e-1, point2.y);

if (pointIndex > 0) {
accLength +=
new THREE.Vector2(p1.x - p0.x, p1.z - p0.z).length() / thick;
}
uvs.push(accLength, 0, accLength, 1);

const color1 = new THREE.Color()
.setHSL(prePoint.length() / 1e1, 1, 0.5)
.toArray();
const color2 = new THREE.Color()
.setHSL(curPoint.length() / 1e1, 1, 0.5)
.toArray();
attributes.colors.push(...color1, ...color1, ...color2, ...color2);
const color = new THREE.Color()
.setHSL(point.length() / 1e1, 1, 0.5)
.toArray();
colors.push(...color, ...color);

const startIndex = (index - 1) * 4;
attributes.indices.push(
if (pointIndex > 0) {
const startIndex = (pointIndex - 1) * 2;
indices.push(
startIndex + 0,
startIndex + 2,
startIndex + 1,
startIndex + 2,
startIndex + 3,
startIndex + 1
);

attributes.uvs.push(...uv1, ...uv2, ...uv3, ...uv4);

return {
latestPoint: point,
attributes,
};
},
{
latestPoint: undefined,
attributes: {
indices: [],
vertices: [],
uvs: [],
colors: [],
},
}
);
}

this.geometry.setIndex(attributes.indices);
this.geometry.setIndex(indices);
this.geometry.setAttribute(
"position",
new THREE.BufferAttribute(new Float32Array(attributes.vertices), 3)
new THREE.BufferAttribute(new Float32Array(vertices), 3)
);
this.geometry.setAttribute(
"uv",
new THREE.BufferAttribute(new Float32Array(attributes.uvs), 2)
new THREE.BufferAttribute(new Float32Array(uvs), 2)
);
this.geometry.setAttribute(
"color",
new THREE.BufferAttribute(new Float32Array(attributes.colors), 3)
new THREE.BufferAttribute(new Float32Array(colors), 3)
);
}
}

0 comments on commit cb15ed3

Please sign in to comment.