fixed hit test on large faces
This commit is contained in:
parent
cf45752848
commit
7d3b8ca232
|
|
@ -110,12 +110,7 @@ export class CircularFrustumIntersection {
|
||||||
: 'NOT_INTERSECTED';
|
: 'NOT_INTERSECTED';
|
||||||
}
|
}
|
||||||
|
|
||||||
// ─── Local frustum construction ──────────────────────────────────────────────
|
//world-space to an object's local space
|
||||||
|
|
||||||
/**
|
|
||||||
* Transform a world-space CircularFrustum into an object's local space.
|
|
||||||
* Note: halfAngle is only preserved exactly under uniform scale.
|
|
||||||
*/
|
|
||||||
private toObjectLocalSpace(invWorldMatrix: THREE.Matrix4): CircularFrustum {
|
private toObjectLocalSpace(invWorldMatrix: THREE.Matrix4): CircularFrustum {
|
||||||
return this.frustum.transform(invWorldMatrix);
|
return this.frustum.transform(invWorldMatrix);
|
||||||
}
|
}
|
||||||
|
|
@ -140,6 +135,8 @@ export class CircularFrustumIntersection {
|
||||||
if (this.insersectsSphere(boundingSphere) === 'NOT_INTERSECTED')
|
if (this.insersectsSphere(boundingSphere) === 'NOT_INTERSECTED')
|
||||||
return [];
|
return [];
|
||||||
|
|
||||||
|
const axisRay = new THREE.Ray(localFrustum.apex, localFrustum.axisNormalized);
|
||||||
|
|
||||||
const results: HitResult[] = [];
|
const results: HitResult[] = [];
|
||||||
|
|
||||||
if (!geometry.boundsTree)
|
if (!geometry.boundsTree)
|
||||||
|
|
@ -208,12 +205,19 @@ export class CircularFrustumIntersection {
|
||||||
tryPoint(a.clone().addScaledVector(edge, tApex));
|
tryPoint(a.clone().addScaledVector(edge, tApex));
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. Closest point on the triangle face to the apex
|
// 3. Closest point on triangle face to the apex (using THREE.Triangle, not ExtendedTriangle)
|
||||||
|
const threeTri = new THREE.Triangle(tri.a, tri.b, tri.c);
|
||||||
const closestOnFace = new THREE.Vector3();
|
const closestOnFace = new THREE.Vector3();
|
||||||
tri.closestPointToPoint(localFrustum.apex, closestOnFace);
|
threeTri.closestPointToPoint(localFrustum.apex, closestOnFace);
|
||||||
if (!isNaN(closestOnFace.x))
|
if (!isNaN(closestOnFace.x))
|
||||||
tryPoint(closestOnFace);
|
tryPoint(closestOnFace);
|
||||||
|
|
||||||
|
// 4. Axis ray through the face — catches large faces the cone passes through
|
||||||
|
const faceHit = new THREE.Vector3();
|
||||||
|
if (axisRay.intersectTriangle(tri.a, tri.b, tri.c, false, faceHit)) {
|
||||||
|
tryPoint(faceHit);
|
||||||
|
}
|
||||||
|
|
||||||
if (bestLocal !== undefined) {
|
if (bestLocal !== undefined) {
|
||||||
const worldPoint = (bestLocal as THREE.Vector3).clone().applyMatrix4(mesh.matrixWorld);
|
const worldPoint = (bestLocal as THREE.Vector3).clone().applyMatrix4(mesh.matrixWorld);
|
||||||
const worldDepth = worldFrustum.axisNormalized.dot(worldPoint.clone().sub(worldFrustum.apex));
|
const worldDepth = worldFrustum.axisNormalized.dot(worldPoint.clone().sub(worldFrustum.apex));
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue