You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于同心圆的递归四叉树细分及2:1过渡优化咨询

同心圆径向四叉树LOD过渡优化问题

我现有一套基于Three.js的四叉树系统,目标是实现同心圆径向LOD细分(相机周围由内到外LOD层级逐渐降低)。目前已通过Box3包围盒实现初步细分,但存在LOD过渡比例为4:1而非预期2:1的问题,需要优化方案。

现有核心代码

LOD同心圆半径计算

_LODCircles(pos){
    const height = pos.y;  // 相机在海面上方的高度
    const lodRadius = [];
    const minRadius = 40;  // 最小LOD层级的半径
    const radius0 = Math.abs(height) > minRadius ? Math.abs(height) : minRadius;
    const qtSize = 200000;  // 四叉树整体尺寸
    const lodSize = Math.log(qtSize/radius0)/Math.LN2;  // 计算LOD层级数量

    for(let i = 0; i < lodSize; i++){
        lodRadius.push(radius0 * 2 ** i);
    }
                            
    return lodRadius;   
}

初步细分实现(存在过渡问题)

_Insert(child, pos, lodCircles){
    const lod0radius = lodCircles[0];
    const lod0Center = pos; // 相机位置
    const closestPoint = new THREE.Vector3();
    child.bounds.clampPoint(lod0Center, closestPoint); 
    const squaredDistance = lod0Center.distanceToSquared(closestPoint);     

    if (squaredDistance <= lod0radius * lod0radius && child.size.x > lodCircles[0] ) {
        child.children = this._CreateChildren(child);
        for (let c of child.children) {
            this._Insert(c, pos, lodCircles);
        }
    }
}

问题分析

当前代码仅以最内层LOD半径(lodCircles[0])作为判断依据:

  • 只有当节点到相机的距离小于最内层半径,且节点尺寸大于最内层半径时才会细分
  • 这导致相邻LOD层级的节点尺寸差距为4倍(父节点尺寸是子节点的2倍,而判断条件直接跳过硬匹配最内层半径,跳过了中间层级),最终呈现4:1的过渡比例

优化方案

核心思路是为每个节点匹配对应的LOD层级,根据节点所在的同心圆范围决定是否细分,确保相邻层级的过渡为2:1:

_Insert(child, pos, lodCircles){
    const closestPoint = new THREE.Vector3();
    child.bounds.clampPoint(pos, closestPoint); 
    const squaredDistance = pos.distanceToSquared(closestPoint);
    const distance = Math.sqrt(squaredDistance);

    // 找到当前节点对应的LOD层级:第一个半径大于等于节点到相机距离的层级
    let targetLodIndex = lodCircles.findIndex(radius => radius >= distance);
    // 如果所有层级半径都小于距离,取最外层层级
    if(targetLodIndex === -1) targetLodIndex = lodCircles.length - 1;

    // 当前层级对应的最小节点尺寸:lodCircles[targetLodIndex] / 2(确保子节点尺寸匹配下一层LOD)
    const minNodeSizeForCurrentLod = lodCircles[targetLodIndex] / 2;

    // 细分条件:节点尺寸大于当前层级允许的最小尺寸,且节点处于当前LOD层级的范围内
    if (child.size.x > minNodeSizeForCurrentLod) {
        child.children = this._CreateChildren(child);
        for (let c of child.children) {
            this._Insert(c, pos, lodCircles);
        }
    }
}

优化说明

  1. 动态匹配LOD层级:根据节点到相机的距离,找到对应的LOD同心圆层级,避免仅用最内层半径判断
  2. 调整最小节点尺寸阈值:将细分阈值设置为当前层级半径的1/2,确保子节点尺寸刚好匹配下一层LOD的要求,实现2:1的过渡比例
  3. 层级覆盖完整:处理节点超出所有同心圆范围的情况,确保最外层LOD的正确显示

额外优化建议

  • 增加相邻节点层级锁定:避免出现单个节点跨层级细分的情况(比如父节点不细分但子节点细分),可以在细分时检查相邻节点的LOD层级,强制保持过渡的连续性
  • 缓存距离计算结果:减少重复的distanceToSquared和开方运算,提升性能

内容的提问来源于stack exchange,提问作者Spiri

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 02:24:53