From ee2cba327362e314328641ad694f6fb5eb825b37 Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Wed, 21 Oct 2026 01:06:20 +0800 Subject: [PATCH] =?UTF-8?q?fix(ignore):=20=E6=94=B9=E7=94=A8=E5=B1=80?= =?UTF-8?q?=E9=83=A8=E5=9D=90=E6=A0=87=E7=9A=84=E7=AB=96=E7=9B=B4=E8=B7=A8?= =?UTF-8?q?=E5=BA=A6=E5=88=A4=E5=AE=9A=E6=A0=85=E6=A0=8F=EF=BC=8C=E4=BF=AE?= =?UTF-8?q?=E6=AD=A3=E4=B8=96=E7=95=8C/=E5=B1=80=E9=83=A8=E5=9D=90?= =?UTF-8?q?=E6=A0=87=E6=B7=B7=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 三角形顶点是刚体局部坐标(诊断里位置恒为 0,0,0),之前拿局部 z 与车体世界 z 比较导致条件恒不成立。现判据:|法线z|<0.6 且本地竖直跨度>100(地面跨度≈0、栅栏≈200+);诊断输出补 解包type/跨度,位置改用刚体世界坐标以便识别近邻节点。 --- tools/hornet_noclip.js | 71 ++++++++++++++++++++---------------------- 1 file changed, 33 insertions(+), 38 deletions(-) diff --git a/tools/hornet_noclip.js b/tools/hornet_noclip.js index d1b4380..0285776 100644 --- a/tools/hornet_noclip.js +++ b/tools/hornet_noclip.js @@ -163,42 +163,31 @@ return !IsTankShape(Shape); } - var FPhysicsPosition = Fld('Physics.Position', 'bzr_1'); // 本地坦克世界位置 - - function LocalTankZ() { - var Phys = GetLocalPhysics(); - var P = Phys && Phys[FPhysicsPosition]; - return (P && typeof P.h20_1 === 'number') ? P.h20_1 : null; - } - - function ShapeMaxZ(Shape) { + // 三角形竖直跨度(局部坐标):顶点 z 的 max-min + // 地面/缓坡:三个顶点几乎同高 → 跨度≈0 + // 栅栏/墙:竖直面 → 跨度大(≥1m) + function TriangleZRange(Shape) { var S = UnwrapShape(Shape); - if (S && S[FShapeType] === TRIANGLE_TYPE) { - var A = S[FV0], B = S[FV1], C = S[FV2]; - if (!A || !B || !C) return null; - var Max = Math.max(A.h20_1, B.h20_1, C.h20_1); - return isFinite(Max) ? Max : null; - } - var Body = Shape[FShapeBody]; - var State = Body && Body[FBodyState]; - var P = State && State[FBodyPosVec]; - return (P && typeof P.h20_1 === 'number') ? P.h20_1 : null; + if (!S || S[FShapeType] !== TRIANGLE_TYPE) return null; + var A = S[FV0], B = S[FV1], C = S[FV2]; + if (!A || !B || !C) return null; + if (typeof A.h20_1 !== 'number' || typeof B.h20_1 !== 'number' || typeof C.h20_1 !== 'number') return null; + var Max = Math.max(A.h20_1, B.h20_1, C.h20_1); + var Min = Math.min(A.h20_1, B.h20_1, C.h20_1); + return Max - Min; } - // 「栅栏类」= 静态几何中的**立面三角形**: - // · 必须是三角形(type 8)—— 非三角形静态体(type 1/4 等)是地面/地形代理,跳过会导致掉出地图 - // · 最高点高于车体中心 1m(地面/缓坡不满足) - // · |法线 z| < 0.6(竖直立面) + // 「栅栏类」= 静态几何中的**立面三角形**(全部用局部坐标判定,不依赖世界坐标): + // · type 4 先解包到真实形状,必须是三角形 + // · |法线 z| < 0.6 → 竖直立面(地面法线≈1) + // · 竖直跨度 > 100 单位 → 有高度的墙/栅栏(地面/缓坡跨度≈0) function IsFenceLike(Shape) { if (!IsStaticShape(Shape)) return false; if (!IsTriangle(Shape)) return false; - var TankZ = LocalTankZ(); - if (TankZ === null) return false; - var MaxZ = ShapeMaxZ(Shape); - if (MaxZ === null) return false; - if (MaxZ < TankZ + 100) return false; var Nz = TriangleNormalZ(Shape); - return Nz !== null && Math.abs(Nz) < 0.6; + if (Nz === null || Math.abs(Nz) >= 0.6) return false; + var Range = TriangleZRange(Shape); + return Range !== null && Range > 100; } // 本车形状 / 本车与栅栏形状的配对(q9q 与 x9o 共用同一套判定) @@ -227,6 +216,12 @@ function ShapePoint(Shape) { if (!Shape) return null; + // 顶点是刚体局部坐标(常见 (0,0,0) 附近),诊断要用刚体的世界位置 + var Body = Shape[FShapeBody]; + var State = Body && Body[FBodyState]; + var P = State && State[FBodyPosVec]; + if (P && typeof P.f20_1 === 'number') return { x: P.f20_1, y: P.g20_1, z: P.h20_1 }; + // 兜底:局部顶点重心 var S = UnwrapShape(Shape); if (S && S[FShapeType] === TRIANGLE_TYPE) { var A = S[FV0], B = S[FV1], C = S[FV2]; @@ -237,13 +232,7 @@ z: (A.h20_1 + B.h20_1 + C.h20_1) / 3 }; } - return null; } - // 非三角形:取所在刚体的世界位置 - var Body = Shape[FShapeBody]; - var State = Body && Body[FBodyState]; - var P = State && State[FBodyPosVec]; - if (P && typeof P.f20_1 === 'number') return { x: P.f20_1, y: P.g20_1, z: P.h20_1 }; return null; } @@ -291,14 +280,20 @@ var Type = Shape[FShapeType]; var Tri = IsTriangle(Shape); var Nz = TriangleNormalZ(Shape); - var Key = Cat + '/' + Type + '/' + (Nz === null ? '-' : Nz.toFixed(2)); + var Base = UnwrapShape(Shape); + var BaseType = Base ? Base[FShapeType] : '-'; + var Range = TriangleZRange(Shape); + var Key = Cat + '/' + Type + '/' + BaseType + '/' + + (Nz === null ? '-' : Nz.toFixed(1)) + '/' + + (Range === null ? '-' : Math.round(Range / 50)); if (FenceSampleKeys[Key]) return; FenceSampleKeys[Key] = 1; var Pt = ShapePoint(Shape); var Near = FindNearNodeNames(Pt, 700); - console.log('[忽略][重叠物体] cat=' + Cat + ' type=' + Type + ' 三角=' + Tri + - ' nz=' + (Nz === null ? '-' : Nz.toFixed(2)) + + console.log('[忽略][重叠物体] cat=' + Cat + ' type=' + Type + ' 解包type=' + BaseType + + ' 三角=' + Tri + ' nz=' + (Nz === null ? '-' : Nz.toFixed(2)) + + ' 跨度=' + (Range === null ? '-' : Range.toFixed(0)) + ' 位置=' + (Pt ? ('(' + Pt.x.toFixed(0) + ',' + Pt.y.toFixed(0) + ',' + Pt.z.toFixed(0) + ')') : '-') + ' 近邻节点=[' + Near.join(', ') + ']' + ' 当前判定=' + (IsFenceLike(Shape) ? '忽略' : '保留'));