Skip to content

Commit

Permalink
Line: Honor last segment of LineLoop in raycast(). (#28114)
Browse files Browse the repository at this point in the history
* Line: implement raycast() method for LineLoop

* Line(#28114): changes for better consistency with Mesh.js

---------

Co-authored-by: 唐壤 <tangrang@minieye.cc>
  • Loading branch information
zoeeer and 唐壤 committed Apr 17, 2024
1 parent 34cfc4d commit 70e7f55
Showing 1 changed file with 66 additions and 43 deletions.
109 changes: 66 additions & 43 deletions src/objects/Line.js
Expand Up @@ -7,12 +7,16 @@ import { LineBasicMaterial } from '../materials/LineBasicMaterial.js';
import { BufferGeometry } from '../core/BufferGeometry.js';
import { Float32BufferAttribute } from '../core/BufferAttribute.js';

const _start = /*@__PURE__*/ new Vector3();
const _end = /*@__PURE__*/ new Vector3();
const _vStart = /*@__PURE__*/ new Vector3();
const _vEnd = /*@__PURE__*/ new Vector3();

const _inverseMatrix = /*@__PURE__*/ new Matrix4();
const _ray = /*@__PURE__*/ new Ray();
const _sphere = /*@__PURE__*/ new Sphere();

const _intersectPointOnRay = /*@__PURE__*/ new Vector3();
const _intersectPointOnSegment = /*@__PURE__*/ new Vector3();

class Line extends Object3D {

constructor( geometry = new BufferGeometry(), material = new LineBasicMaterial() ) {
Expand Down Expand Up @@ -54,11 +58,11 @@ class Line extends Object3D {

for ( let i = 1, l = positionAttribute.count; i < l; i ++ ) {

_start.fromBufferAttribute( positionAttribute, i - 1 );
_end.fromBufferAttribute( positionAttribute, i );
_vStart.fromBufferAttribute( positionAttribute, i - 1 );
_vEnd.fromBufferAttribute( positionAttribute, i );

lineDistances[ i ] = lineDistances[ i - 1 ];
lineDistances[ i ] += _start.distanceTo( _end );
lineDistances[ i ] += _vStart.distanceTo( _vEnd );

}

Expand Down Expand Up @@ -99,10 +103,6 @@ class Line extends Object3D {
const localThreshold = threshold / ( ( this.scale.x + this.scale.y + this.scale.z ) / 3 );
const localThresholdSq = localThreshold * localThreshold;

const vStart = new Vector3();
const vEnd = new Vector3();
const interSegment = new Vector3();
const interRay = new Vector3();
const step = this.isLineSegments ? 2 : 1;

const index = geometry.index;
Expand All @@ -119,31 +119,28 @@ class Line extends Object3D {
const a = index.getX( i );
const b = index.getX( i + 1 );

vStart.fromBufferAttribute( positionAttribute, a );
vEnd.fromBufferAttribute( positionAttribute, b );
const intersect = checkIntersection( this, raycaster, _ray, localThresholdSq, a, b );

if ( intersect ) {

const distSq = _ray.distanceSqToSegment( vStart, vEnd, interRay, interSegment );
intersects.push( intersect );

if ( distSq > localThresholdSq ) continue;
}

}

interRay.applyMatrix4( this.matrixWorld ); //Move back to world space for distance calculation
if ( this.isLineLoop ) {

const distance = raycaster.ray.origin.distanceTo( interRay );
const a = index.getX( end - 1 );
const b = index.getX( start );

if ( distance < raycaster.near || distance > raycaster.far ) continue;
const intersect = checkIntersection( this, raycaster, _ray, localThresholdSq, a, b );

intersects.push( {
if ( intersect ) {

distance: distance,
// What do we want? intersection point on the ray or on the segment??
// point: raycaster.ray.at( distance ),
point: interSegment.clone().applyMatrix4( this.matrixWorld ),
index: i,
face: null,
faceIndex: null,
object: this
intersects.push( intersect );

} );
}

}

Expand All @@ -154,31 +151,25 @@ class Line extends Object3D {

for ( let i = start, l = end - 1; i < l; i += step ) {

vStart.fromBufferAttribute( positionAttribute, i );
vEnd.fromBufferAttribute( positionAttribute, i + 1 );
const intersect = checkIntersection( this, raycaster, _ray, localThresholdSq, i, i + 1 );

if ( intersect ) {

const distSq = _ray.distanceSqToSegment( vStart, vEnd, interRay, interSegment );
intersects.push( intersect );

if ( distSq > localThresholdSq ) continue;
}

interRay.applyMatrix4( this.matrixWorld ); //Move back to world space for distance calculation
}

const distance = raycaster.ray.origin.distanceTo( interRay );
if ( this.isLineLoop ) {

if ( distance < raycaster.near || distance > raycaster.far ) continue;
const intersect = checkIntersection( this, raycaster, _ray, localThresholdSq, end - 1, start );

intersects.push( {
if ( intersect ) {

distance: distance,
// What do we want? intersection point on the ray or on the segment??
// point: raycaster.ray.at( distance ),
point: interSegment.clone().applyMatrix4( this.matrixWorld ),
index: i,
face: null,
faceIndex: null,
object: this
intersects.push( intersect );

} );
}

}

Expand Down Expand Up @@ -219,4 +210,36 @@ class Line extends Object3D {

}

function checkIntersection( object, raycaster, ray, thresholdSq, a, b ) {

const positionAttribute = object.geometry.attributes.position;

_vStart.fromBufferAttribute( positionAttribute, a );
_vEnd.fromBufferAttribute( positionAttribute, b );

const distSq = ray.distanceSqToSegment( _vStart, _vEnd, _intersectPointOnRay, _intersectPointOnSegment );

if ( distSq > thresholdSq ) return;

_intersectPointOnRay.applyMatrix4( object.matrixWorld ); // Move back to world space for distance calculation

const distance = raycaster.ray.origin.distanceTo( _intersectPointOnRay );

if ( distance < raycaster.near || distance > raycaster.far ) return;

return {

distance: distance,
// What do we want? intersection point on the ray or on the segment??
// point: raycaster.ray.at( distance ),
point: _intersectPointOnSegment.clone().applyMatrix4( object.matrixWorld ),
index: a,
face: null,
faceIndex: null,
object: object

};

}

export { Line };

0 comments on commit 70e7f55

Please sign in to comment.