Skip to content

Instantly share code, notes, and snippets.

@tommie
Last active September 8, 2024 09:53
Show Gist options
  • Save tommie/1a4b485d9f34ed9ca7cb78d4ae78310b to your computer and use it in GitHub Desktop.
Save tommie/1a4b485d9f34ed9ca7cb78d4ae78310b to your computer and use it in GitHub Desktop.
import * as THREE from "three";
function isLineBasicMaterial(mat: THREE.Material & { isLineBasicMaterial?: boolean }): mat is THREE.LineBasicMaterial {
return Boolean(mat.isLineBasicMaterial);
}
function isOrthographicCamera(camera: THREE.Camera & { isOrthographicCamera?: boolean }): camera is THREE.OrthographicCamera {
return Boolean(camera.isOrthographicCamera);
}
// Returns the maximum line width in `mat`, or undefined.
function getLineWidth(mat: THREE.Material | THREE.Material[]) {
if (Array.isArray(mat)) {
let maxWidth = 0;
for (const m of mat) {
if (isLineBasicMaterial(m) && m.linewidth > maxWidth) {
maxWidth = m.linewidth;
}
}
} else {
if (isLineBasicMaterial(mat)) {
return mat.linewidth;
}
}
return undefined;
}
interface ExtendedRaycasterParameters extends THREE.RaycasterParameters {
Line: THREE.RaycasterParameters["Line"] & {
// Whether to perform ray casting based on `LineBasicMaterial`
// properties.
material?: boolean;
};
}
// Returns the type-cast parameters.
export function getExtendedRaycasterParams(raycaster: THREE.Raycaster) {
return raycaster.params as ExtendedRaycasterParameters;
}
// A Line that can perform ray casting based on
// `LineBasicMaterial.linewidth`. This behavior is enabled if
// `raycaster.params.Line.screenSpace` is true.
//
// Workaround for https://github.com/mrdoob/three.js/issues/29353.
export class Line2 extends THREE.Line {
override raycast(raycaster: THREE.Raycaster, intersects: THREE.Intersection[]) {
const params = getExtendedRaycasterParams(raycaster).Line;
if (params.material) {
if (!this.material) return undefined;
let lw = getLineWidth(this.material);
if (lw === undefined) return undefined;
if (isOrthographicCamera(raycaster.camera)) {
lw /= raycaster.camera.zoom;
}
params.threshold = lw;
}
return super.raycast(raycaster, intersects);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment