186 lines
5.6 KiB
TypeScript
186 lines
5.6 KiB
TypeScript
// import { Line } from "@react-three/drei";
|
|
// import { useThree } from "@react-three/fiber";
|
|
// import { useEffect, useMemo, useRef } from "react";
|
|
// import { CubicBezierCurve3, LineCurve3, Plane, Vector3 } from "three";
|
|
|
|
// export default function LineSegment({
|
|
// index,
|
|
// createdPoints,
|
|
// updatePoints,
|
|
// insertPoint,
|
|
// }: {
|
|
// index: number;
|
|
// createdPoints: any[]; // Array of points with position, isCurved, handleA, handleB
|
|
// updatePoints: (i0: number, p0: Vector3, i1: number, p1: Vector3) => void;
|
|
// insertPoint?: (index: number, point: Vector3) => void;
|
|
// }) {
|
|
// const { gl, raycaster, camera, controls } = useThree();
|
|
// const plane = new Plane(new Vector3(0, 1, 0), 0);
|
|
// const dragStart = useRef<Vector3 | null>(null);
|
|
|
|
// // ======== Curve or Line Points ========
|
|
// const curvePoints = useMemo(() => {
|
|
// if (!createdPoints || index + 1 >= createdPoints.length) return [];
|
|
|
|
// const current = createdPoints[index];
|
|
// const next = createdPoints[index + 1];
|
|
|
|
// const starts = new Vector3(...current.position);
|
|
// const ends = new Vector3(...next.position);
|
|
|
|
// const useCurve =
|
|
// (current.isCurved && current.handleB) || (next.isCurved && next.handleA);
|
|
|
|
// const hB = current.handleB ? new Vector3(...current.handleB) : starts;
|
|
// const hA = next.handleA ? new Vector3(...next.handleA) : ends;
|
|
|
|
// const curve = useCurve
|
|
// ? new CubicBezierCurve3(starts, hB, hA, ends)
|
|
// : new LineCurve3(starts, ends);
|
|
|
|
// return curve.getPoints(useCurve ? 100 : 2);
|
|
// }, [createdPoints, index]);
|
|
|
|
// // ======== Events ========
|
|
// const onPointerUp = () => {
|
|
// dragStart.current = null;
|
|
// gl.domElement.style.cursor = "default";
|
|
// if (controls) (controls as any).enabled = true;
|
|
// };
|
|
|
|
// const onClickLine = () => {
|
|
// const intersection = new Vector3();
|
|
// if (raycaster.ray.intersectPlane(plane, intersection)) {
|
|
// const start = new Vector3(...createdPoints[index].position);
|
|
// const end = new Vector3(...createdPoints[index + 1].position);
|
|
// const segLen = start.distanceTo(end);
|
|
// const distToStart = start.distanceTo(intersection);
|
|
// const distToEnd = end.distanceTo(intersection);
|
|
|
|
// if (
|
|
// distToStart > 0.01 &&
|
|
// distToEnd > 0.01 &&
|
|
// distToStart + distToEnd <= segLen + 0.01
|
|
// ) {
|
|
// insertPoint?.(index + 1, intersection);
|
|
// }
|
|
// }
|
|
// };
|
|
|
|
// useEffect(() => {
|
|
// gl.domElement.addEventListener("pointerup", onPointerUp);
|
|
// return () => {
|
|
// gl.domElement.removeEventListener("pointerup", onPointerUp);
|
|
// };
|
|
// }, []);
|
|
|
|
// // ======== Render ========
|
|
// return (
|
|
// <Line
|
|
// points={curvePoints}
|
|
// color="purple"
|
|
// lineWidth={2}
|
|
// onPointerDown={onClickLine}
|
|
// onPointerUp={onPointerUp}
|
|
// />
|
|
// );
|
|
// }
|
|
import { Line } from "@react-three/drei";
|
|
import { useThree } from "@react-three/fiber";
|
|
import { useEffect, useMemo, useRef } from "react";
|
|
import { CubicBezierCurve3, LineCurve3, Plane, Vector3 } from "three";
|
|
|
|
export default function LineSegment({
|
|
index,
|
|
createdPoints,
|
|
updatePoints,
|
|
insertPoint,
|
|
}: {
|
|
index: number;
|
|
createdPoints: any[];
|
|
updatePoints: (i0: number, p0: Vector3, i1: number, p1: Vector3) => void;
|
|
insertPoint?: (index: number, point: Vector3) => void;
|
|
}) {
|
|
const { gl, raycaster, camera, controls } = useThree();
|
|
const plane = new Plane(new Vector3(0, 1, 0), 0);
|
|
const dragStart = useRef<Vector3 | null>(null);
|
|
|
|
const curvePoints = useMemo(() => {
|
|
if (!createdPoints || index + 1 >= createdPoints.length) return [];
|
|
|
|
const current = createdPoints[index];
|
|
const next = createdPoints[index + 1];
|
|
|
|
// Force y = 0
|
|
const starts = new Vector3(current.position[0], 0, current.position[2]);
|
|
const ends = new Vector3(next.position[0], 0, next.position[2]);
|
|
|
|
const useCurve =
|
|
(current.isCurved && current.handleB) || (next.isCurved && next.handleA);
|
|
|
|
const hB = current.handleB
|
|
? new Vector3(current.handleB[0], 0, current.handleB[2])
|
|
: starts;
|
|
const hA = next.handleA
|
|
? new Vector3(next.handleA[0], 0, next.handleA[2])
|
|
: ends;
|
|
|
|
const curve = useCurve
|
|
? new CubicBezierCurve3(starts, hB, hA, ends)
|
|
: new LineCurve3(starts, ends);
|
|
|
|
return curve.getPoints(useCurve ? 100 : 2);
|
|
}, [createdPoints, index]);
|
|
|
|
const onPointerUp = () => {
|
|
dragStart.current = null;
|
|
gl.domElement.style.cursor = "default";
|
|
if (controls) (controls as any).enabled = true;
|
|
};
|
|
|
|
const onClickLine = () => {
|
|
const intersection = new Vector3();
|
|
if (raycaster.ray.intersectPlane(plane, intersection)) {
|
|
const start = new Vector3(
|
|
createdPoints[index].position[0],
|
|
0,
|
|
createdPoints[index].position[2]
|
|
);
|
|
const end = new Vector3(
|
|
createdPoints[index + 1].position[0],
|
|
0,
|
|
createdPoints[index + 1].position[2]
|
|
);
|
|
|
|
const segLen = start.distanceTo(end);
|
|
const distToStart = start.distanceTo(intersection);
|
|
const distToEnd = end.distanceTo(intersection);
|
|
|
|
if (
|
|
distToStart > 0.01 &&
|
|
distToEnd > 0.01 &&
|
|
distToStart + distToEnd <= segLen + 0.01
|
|
) {
|
|
insertPoint?.(index + 1, intersection);
|
|
}
|
|
}
|
|
};
|
|
|
|
useEffect(() => {
|
|
gl.domElement.addEventListener("pointerup", onPointerUp);
|
|
return () => {
|
|
gl.domElement.removeEventListener("pointerup", onPointerUp);
|
|
};
|
|
}, []);
|
|
|
|
return (
|
|
<Line
|
|
points={curvePoints}
|
|
color="purple"
|
|
lineWidth={2}
|
|
onPointerDown={onClickLine}
|
|
onPointerUp={onPointerUp}
|
|
/>
|
|
);
|
|
}
|