fix(wireframe): 去重键去掉世界坐标并取消扫描节流,修复模型闪烁
This commit is contained in:
1 parent
a83f2a5407
commit
41b94ef0f9
3 files changed
+21
-60
No files matched your search
@@ -2082,9 +2082,9 @@
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
// 结果级去重:同一 mesh 资源 + 同一世界平移,只保留一份
|
||||
// (引擎里同一逻辑节点可能存在「皮肤树 / 场景树」两套实例,AABB/矩阵更新时机不同,
|
||||
// 两套都画会出现「复制出一个不动的身体,过一会才跟上」)
|
||||
// 结果级去重:同一 mesh 资源 + 同一节点名,只保留一份
|
||||
// 注意:**不要把世界坐标写进键**——坦克移动时两套实例的平移会差一帧,
|
||||
// 键随位置变化会导致「这帧去重、下帧不去重」→ 模型闪烁。
|
||||
var TpIds = new WeakMap();
|
||||
var TpNextId = 1;
|
||||
function DedupNodes(nodes) {
|
||||
@@ -2096,9 +2096,7 @@
|
||||
var Tp = N.tp;
|
||||
var Id = TpIds.get(Tp);
|
||||
if (!Id) { Id = TpNextId++; TpIds.set(Tp, Id); }
|
||||
var M = N.node && N.node.p35_1;
|
||||
var Pos = M ? (Math.round(M[12]) + ',' + Math.round(M[13]) + ',' + Math.round(M[14])) : '?';
|
||||
var Key = Id + ':' + N.name + ':' + Pos;
|
||||
var Key = Id + ':' + N.name;
|
||||
if (Keys.has(Key)) continue;
|
||||
Keys.add(Key);
|
||||
Out.push(N);
|
||||
@@ -2106,20 +2104,9 @@
|
||||
return Out;
|
||||
}
|
||||
|
||||
// 扫描节流:仅在主路径完全采不到时使用,且同一辆坦克至少间隔 10 帧
|
||||
var ScanTick = 0;
|
||||
var LastScanAt = new WeakMap();
|
||||
function ShouldScanNow(tank) {
|
||||
ScanTick++;
|
||||
var Last = LastScanAt.get(tank) || 0;
|
||||
if (ScanTick - Last < 10) return false;
|
||||
LastScanAt.set(tank, ScanTick);
|
||||
return true;
|
||||
}
|
||||
|
||||
// ===== 提取坦克的mesh数据 =====
|
||||
// 采集策略:**单一路径优先**,绝不把两条路径的结果混在一起(混在一起就是"复制身体")
|
||||
// ① 皮肤组件 h159_1(实际渲染树根)→ ② 部件表 → ③ 组件字段扫描(节流兜底)
|
||||
// ① 皮肤组件 h159_1(实际渲染树根)→ ② 部件表 → ③ 组件字段扫描(兜底)
|
||||
function GetTankMeshData(tank, stats) {
|
||||
var nodes = [];
|
||||
var Seen = new WeakSet();
|
||||
@@ -2150,8 +2137,8 @@
|
||||
});
|
||||
} catch(e) {}
|
||||
}
|
||||
// ③ 仍然为空才做组件字段扫描(节流,避免每帧全量遍历造成卡顿)
|
||||
if (nodes.length === 0 && ShouldScanNow(tank)) {
|
||||
// ③ 仍然为空才做组件字段扫描(不加节流:节流会导致「这帧有模型、下帧只有点」的闪烁)
|
||||
if (nodes.length === 0) {
|
||||
try { ScanMeshNodes(tank, nodes, stats ? stats.scan : null, Seen); } catch (e) {}
|
||||
}
|
||||
// ④ 炮塔(独立于车身根;重复实例由 DedupNodes 收掉)
|
||||
|
||||
+7
-20
@@ -2082,9 +2082,9 @@
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
// 结果级去重:同一 mesh 资源 + 同一世界平移,只保留一份
|
||||
// (引擎里同一逻辑节点可能存在「皮肤树 / 场景树」两套实例,AABB/矩阵更新时机不同,
|
||||
// 两套都画会出现「复制出一个不动的身体,过一会才跟上」)
|
||||
// 结果级去重:同一 mesh 资源 + 同一节点名,只保留一份
|
||||
// 注意:**不要把世界坐标写进键**——坦克移动时两套实例的平移会差一帧,
|
||||
// 键随位置变化会导致「这帧去重、下帧不去重」→ 模型闪烁。
|
||||
var TpIds = new WeakMap();
|
||||
var TpNextId = 1;
|
||||
function DedupNodes(nodes) {
|
||||
@@ -2096,9 +2096,7 @@
|
||||
var Tp = N.tp;
|
||||
var Id = TpIds.get(Tp);
|
||||
if (!Id) { Id = TpNextId++; TpIds.set(Tp, Id); }
|
||||
var M = N.node && N.node.p35_1;
|
||||
var Pos = M ? (Math.round(M[12]) + ',' + Math.round(M[13]) + ',' + Math.round(M[14])) : '?';
|
||||
var Key = Id + ':' + N.name + ':' + Pos;
|
||||
var Key = Id + ':' + N.name;
|
||||
if (Keys.has(Key)) continue;
|
||||
Keys.add(Key);
|
||||
Out.push(N);
|
||||
@@ -2106,20 +2104,9 @@
|
||||
return Out;
|
||||
}
|
||||
|
||||
// 扫描节流:仅在主路径完全采不到时使用,且同一辆坦克至少间隔 10 帧
|
||||
var ScanTick = 0;
|
||||
var LastScanAt = new WeakMap();
|
||||
function ShouldScanNow(tank) {
|
||||
ScanTick++;
|
||||
var Last = LastScanAt.get(tank) || 0;
|
||||
if (ScanTick - Last < 10) return false;
|
||||
LastScanAt.set(tank, ScanTick);
|
||||
return true;
|
||||
}
|
||||
|
||||
// ===== 提取坦克的mesh数据 =====
|
||||
// 采集策略:**单一路径优先**,绝不把两条路径的结果混在一起(混在一起就是"复制身体")
|
||||
// ① 皮肤组件 h159_1(实际渲染树根)→ ② 部件表 → ③ 组件字段扫描(节流兜底)
|
||||
// ① 皮肤组件 h159_1(实际渲染树根)→ ② 部件表 → ③ 组件字段扫描(兜底)
|
||||
function GetTankMeshData(tank, stats) {
|
||||
var nodes = [];
|
||||
var Seen = new WeakSet();
|
||||
@@ -2150,8 +2137,8 @@
|
||||
});
|
||||
} catch(e) {}
|
||||
}
|
||||
// ③ 仍然为空才做组件字段扫描(节流,避免每帧全量遍历造成卡顿)
|
||||
if (nodes.length === 0 && ShouldScanNow(tank)) {
|
||||
// ③ 仍然为空才做组件字段扫描(不加节流:节流会导致「这帧有模型、下帧只有点」的闪烁)
|
||||
if (nodes.length === 0) {
|
||||
try { ScanMeshNodes(tank, nodes, stats ? stats.scan : null, Seen); } catch (e) {}
|
||||
}
|
||||
// ④ 炮塔(独立于车身根;重复实例由 DedupNodes 收掉)
|
||||
|
||||
@@ -557,9 +557,9 @@
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
// 结果级去重:同一 mesh 资源 + 同一世界平移,只保留一份
|
||||
// (引擎里同一逻辑节点可能存在「皮肤树 / 场景树」两套实例,AABB/矩阵更新时机不同,
|
||||
// 两套都画会出现「复制出一个不动的身体,过一会才跟上」)
|
||||
// 结果级去重:同一 mesh 资源 + 同一节点名,只保留一份
|
||||
// 注意:**不要把世界坐标写进键**——坦克移动时两套实例的平移会差一帧,
|
||||
// 键随位置变化会导致「这帧去重、下帧不去重」→ 模型闪烁。
|
||||
var TpIds = new WeakMap();
|
||||
var TpNextId = 1;
|
||||
function DedupNodes(nodes) {
|
||||
@@ -571,9 +571,7 @@
|
||||
var Tp = N.tp;
|
||||
var Id = TpIds.get(Tp);
|
||||
if (!Id) { Id = TpNextId++; TpIds.set(Tp, Id); }
|
||||
var M = N.node && N.node.p35_1;
|
||||
var Pos = M ? (Math.round(M[12]) + ',' + Math.round(M[13]) + ',' + Math.round(M[14])) : '?';
|
||||
var Key = Id + ':' + N.name + ':' + Pos;
|
||||
var Key = Id + ':' + N.name;
|
||||
if (Keys.has(Key)) continue;
|
||||
Keys.add(Key);
|
||||
Out.push(N);
|
||||
@@ -581,20 +579,9 @@
|
||||
return Out;
|
||||
}
|
||||
|
||||
// 扫描节流:仅在主路径完全采不到时使用,且同一辆坦克至少间隔 10 帧
|
||||
var ScanTick = 0;
|
||||
var LastScanAt = new WeakMap();
|
||||
function ShouldScanNow(tank) {
|
||||
ScanTick++;
|
||||
var Last = LastScanAt.get(tank) || 0;
|
||||
if (ScanTick - Last < 10) return false;
|
||||
LastScanAt.set(tank, ScanTick);
|
||||
return true;
|
||||
}
|
||||
|
||||
// ===== 提取坦克的mesh数据 =====
|
||||
// 采集策略:**单一路径优先**,绝不把两条路径的结果混在一起(混在一起就是"复制身体")
|
||||
// ① 皮肤组件 h159_1(实际渲染树根)→ ② 部件表 → ③ 组件字段扫描(节流兜底)
|
||||
// ① 皮肤组件 h159_1(实际渲染树根)→ ② 部件表 → ③ 组件字段扫描(兜底)
|
||||
function GetTankMeshData(tank, stats) {
|
||||
var nodes = [];
|
||||
var Seen = new WeakSet();
|
||||
@@ -625,8 +612,8 @@
|
||||
});
|
||||
} catch(e) {}
|
||||
}
|
||||
// ③ 仍然为空才做组件字段扫描(节流,避免每帧全量遍历造成卡顿)
|
||||
if (nodes.length === 0 && ShouldScanNow(tank)) {
|
||||
// ③ 仍然为空才做组件字段扫描(不加节流:节流会导致「这帧有模型、下帧只有点」的闪烁)
|
||||
if (nodes.length === 0) {
|
||||
try { ScanMeshNodes(tank, nodes, stats ? stats.scan : null, Seen); } catch (e) {}
|
||||
}
|
||||
// ④ 炮塔(独立于车身根;重复实例由 DedupNodes 收掉)
|
||||
|
||||
Reference in new issue
Block a user