Last active
September 8, 2024 09:53
-
-
Save tommie/1a4b485d9f34ed9ca7cb78d4ae78310b to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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