Ray only hit the latest element in my list of collidable object

Hello! I’m facing some logic issue here.

I’m currently doing a raycast through a list of meshes (collidable list) to add some kind of effect (hitTrajectory) at the hit position. At the moment, everything is working fine. However, I noticed that the effect is only positionned on the latest object in the array that the ray collides with.

For example, the effect will always be on the ball even if a boundery is closer because the balls are the latest meshes added to the array. is there something I’m missing in my conditions? I also took a look at the documentation and the playground related to the rays but I did not find anything. Thanks!

/**
   * Create a list of collidable object that any ray can collide with
   */
  private createCollidableList (): void {
    // Add holes to the list of collidables
    this.table.getHoles().forEach((hole: Hole) => {
      this.collidables.push(hole.getMesh())
    })

    // Add bounderies to the list of collidables
    this.table.getBounderies().forEach((boundery: Boundery) => {
      this.collidables.push(boundery.getMesh())
    })

    // Add balls to the list of collidables
    this.ballManager.getBalls().forEach((ball: Ball) => {
      if (ball.getBallType() !== BallType.White) {
        this.collidables.push(ball.getMesh())
      }
    })
  }

/**
   * Check if a ray collide with an object contained in the collidable object list
   * @param ray CustomRay
   * @param hitTrajectory HitTrajectory
   */
  private checkCollisionWithCollidables (ray: CustomRay, hitTrajectory: HitTrajectory): void {
    this.collidables.forEach((collidable: any) => {
      const hitInfo = ray.intersectsMeshes([collidable])

      if (this.rayHitSomething(hitInfo)) {
        // Get the first hit point
        if (hitInfo[0].pickedPoint != null) {
          // get dray direction
          const rayVector = hitInfo[0].pickedPoint.subtract(ray.origin)
          // Set hit at the hit position with a certain offset
          hitTrajectory.setHitPosition(this.getPointAlongVector(ray.origin, hitInfo[0].pickedPoint, rayVector.length() - 0.35))
        }
      }
    })
  }

  /**
   * Check if a ray hit something
   * @param hitInfo PickingInfo[]
   * @returns boolean
   */
  private rayHitSomething (hitInfo: PickingInfo[]): boolean {
    let hitSomething = false
    for (let i = 0; i < hitInfo.length; i++) {
      if (hitInfo[i].pickedPoint != null) {
        hitSomething = true
      }
    }
    return hitSomething
  }

I hope the chatGPT gives you a proper hint:

GPT:
To solve this issue, you need to store both the hit position and the mesh that was hit for each intersection test. One way to do this is to use an array to store the hit positions and an array to store the meshes that were hit, and then find the closest hit position in the array.

Here’s an example code snippet:

javascriptCopy code

var hitPositions = [];
var hitMeshes = [];

// Iterate through the collidable list
for (var i = 0; i < collidableList.length; i++) {
  var mesh = collidableList[i];
  var result = scene.rayIntersects(ray, mesh);

  // Check for intersection
  if (result.hit) {
    // Store the hit position and the mesh that was hit
    hitPositions.push(result.pickedPoint);
    hitMeshes.push(mesh);
  }
}

// Find the closest hit position
var closestHitIndex = -1;
var closestHitDistance = Number.MAX_VALUE;

for (var i = 0; i < hitPositions.length; i++) {
  var distance = BABYLON.Vector3.Distance(ray.origin, hitPositions[i]);

  if (distance < closestHitDistance) {
    closestHitIndex = i;
    closestHitDistance = distance;
  }
}

// Apply the hit effect at the closest hit position
if (closestHitIndex !== -1) {
  var closestHitPosition = hitPositions[closestHitIndex];
  var closestHitMesh = hitMeshes[closestHitIndex];

  // Apply the hit effect at closestHitPosition on closestHitMesh
}
2 Likes