Torch_HXM 2023-09-13 12:13 采纳率: 40%
浏览 17
已结题

Babylon.js关于遮挡检测的问题

Babylon.js关于遮挡检测的问题

1. API和参数

  • 我使用的API是Mesh.isOccluded
  • Mesh.occlusionType = BABYLON.AbstractMesh.OCCLUSION_TYPE_STRICT
  • Mesh.occlusionQueryAlgorithmType = BABYLON.AbstractMesh.OCCLUSION_ALGORITHM_TYPE_CONSERVATIVE

2. 场景

  • 我创建了一个盒子,并在盒子的表面贴满了贴片

    img

  • 在实际测试时,我的盒子是不透明状态。

3. 问题

  • 我对盒子表面的贴片进行了遮挡检测
  • 在进行检测之前,多次使用Mesh.isOcclusionQueryInProgress来判断系统是否对该Mesh的遮挡进行了计算
  • 然而,盒子在正常视角下最多只会裸露三个面,也就是说,我的贴片应该最多只有一半是可见的,然而,实际测试中发现,可见的贴片始终在半数以上,有的甚至全部可见

4. 相关代码

  •     // 创建贴片
        const plane = new BABYLON.MeshBuilder.CreateBox("p"+i+j, {width:1, height:1, depth:0.01}, scene);
        plane.occlusionQueryAlgorithmType = BABYLON.AbstractMesh.OCCLUSION_ALGORITHM_TYPE_CONSERVATIVE;
        plane.occlusionType = BABYLON.AbstractMesh.OCCLUSION_TYPE_STRICT;
    
  •       // 判断系统是否对mesh的遮挡进行了计算
          // 代码中patches是plane的数组
            let ready_counter = 0;
            function ifOccludedDataReady(box){
              let patches = box.patches;
              let if_ready = true;
    
              if(ready_counter<1){
                for(let i=0;i<6;i++){
                  for(let j=0;j<patches[i].length;j++){
                    if_ready = if_ready && patches[i][j].isOcclusionQueryInProgress;
                    patches[i][j].isOccluded; // weakup
                    if(!if_ready){
                      return false;
                      }
                   }
                }
                ready_counter++;
                return false;
            }
           else{
              ready_counter = 0;
              return true;
           }
         }
    

5. 结果

  • 可以看到,虽然box只裸露了三个表面,但是,所有的plane都处于未被遮挡状态。
  • img

    img

    img

6. 或者我们有没有其他的方法来检测遮挡?

  • 写回答

3条回答 默认 最新

  • CSDN-Ada助手 CSDN-AI 官方账号 2023-09-13 14:55
    关注

    【以下回答由 GPT 生成】

    答案:

    1. 参数Mesh.occlusionType是用来指定遮挡检测类型的。 OCCLUSION_TYPE_STRICT表示使用严格的遮挡检测算法,即只有在场景中完全遮挡住一个物体时才会返回true。OCCLUSION_ALGORITHM_TYPE_CONSERVATIVE表示使用保守的遮挡检测算法,这种算法可能会返回假阳性,即在实际上物体并没有完全遮挡住的情况下也会返回true。

    2. 可能导致遮挡检测结果不符合预期的原因有以下几点:

    3. 盒子的表面贴片可能与相机视角平行,无法进行遮挡检测。因为根据遮挡检测的原理,贴片只有在场景中被其他物体部分或完全遮挡住时才会返回true。
    4. 使用的遮挡检测算法不适用于盒子的表面贴片,导致遮挡检测结果不准确。可能需要尝试其他的遮挡检测算法来解决这个问题。

    5. 以上代码可能导致遮挡检测结果不准确的问题有以下几点:

    6. ifOccludedDataReady函数中的代码在第一次调用时会返回false,因为ready_counter初始值为0,所以条件ready_counter<1为true。这会导致第一次调用遮挡检测结果始终为false,而不进行实际的遮挡检测计算。
    7. 在该函数中,对于每个贴片,只要有一个贴片的遮挡检测结果为false,就会立即返回false。这可能导致贴片的遮挡检测结果不准确,因为只检测了每个贴片的遮挡检测结果,而没有考虑整个盒子表面的遮挡情况。

    解决方案:

    1. 根据问题描述,使用Mesh.isOccluded方法检测物体是否被遮挡的代码是正确的,参数的含义也正确地设置了严格模式的遮挡检测算法。所以第一个问题已经解决。

    2. 贴片遮挡检测结果不符合预期的问题可能是由于以下原因导致的:

    3. 与相机视角平行的贴片无法进行遮挡检测,请确保贴片在场景中被其他物体部分或完全遮挡住。
    4. Mesh.occlusionQueryAlgorithmType参数可能不适用于盒子的表面贴片,尝试使用其他的遮挡检测算法,如BABYLON.AbstractMesh.OCCLUSION_ALGORITHM_TYPE_STRICT

    5. 修正ifOccludedDataReady函数中的问题:

    function ifOccludedDataReady(box) {
      let patches = box.patches;
      let if_ready = true;
    
      if (ready_counter < 1) {
        for (let i = 0; i < 6; i++) {
          for (let j = 0; j < patches[i].length; j++) {
            if_ready = if_ready && patches[i][j].isOcclusionQueryInProgress;
            patches[i][j].isOccluded; // weakup
            if (!if_ready) {
              return false;
            }
          }
        }
        ready_counter++;
        return if_ready; // 修改返回逻辑
      } else {
        ready_counter = 0;
        return true;
      }
    }
    

    通过以上修改,ifOccludedDataReady函数将在所有贴片的遮挡检测结果都准备完毕时才返回true。

    希望以上解决方案能够解决你的问题。如果还有其他问题,请随时提问。


    如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

问题事件

  • 系统已结题 11月4日
  • 已采纳回答 10月27日
  • 创建了问题 9月13日