fix(ignore): 改用局部坐标的竖直跨度判定栅栏,修正世界/局部坐标混用
三角形顶点是刚体局部坐标(诊断里位置恒为 0,0,0),之前拿局部 z 与车体世界 z 比较导致条件恒不成立。现判据:|法线z|<0.6 且本地竖直跨度>100(地面跨度≈0、栅栏≈200+);诊断输出补 解包type/跨度,位置改用刚体世界坐标以便识别近邻节点。
This commit is contained in:
1 parent
4ee63a78c9
commit
ee2cba3273
1 file changed
+33
-38
+33
-38
@@ -163,42 +163,31 @@
|
|||||||
return !IsTankShape(Shape);
|
return !IsTankShape(Shape);
|
||||||
}
|
}
|
||||||
|
|
||||||
var FPhysicsPosition = Fld('Physics.Position', 'bzr_1'); // 本地坦克世界位置
|
// 三角形竖直跨度(局部坐标):顶点 z 的 max-min
|
||||||
|
// 地面/缓坡:三个顶点几乎同高 → 跨度≈0
|
||||||
function LocalTankZ() {
|
// 栅栏/墙:竖直面 → 跨度大(≥1m)
|
||||||
var Phys = GetLocalPhysics();
|
function TriangleZRange(Shape) {
|
||||||
var P = Phys && Phys[FPhysicsPosition];
|
|
||||||
return (P && typeof P.h20_1 === 'number') ? P.h20_1 : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
function ShapeMaxZ(Shape) {
|
|
||||||
var S = UnwrapShape(Shape);
|
var S = UnwrapShape(Shape);
|
||||||
if (S && S[FShapeType] === TRIANGLE_TYPE) {
|
if (!S || S[FShapeType] !== TRIANGLE_TYPE) return null;
|
||||||
var A = S[FV0], B = S[FV1], C = S[FV2];
|
var A = S[FV0], B = S[FV1], C = S[FV2];
|
||||||
if (!A || !B || !C) return null;
|
if (!A || !B || !C) return null;
|
||||||
var Max = Math.max(A.h20_1, B.h20_1, C.h20_1);
|
if (typeof A.h20_1 !== 'number' || typeof B.h20_1 !== 'number' || typeof C.h20_1 !== 'number') return null;
|
||||||
return isFinite(Max) ? Max : 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);
|
||||||
var Body = Shape[FShapeBody];
|
return Max - Min;
|
||||||
var State = Body && Body[FBodyState];
|
|
||||||
var P = State && State[FBodyPosVec];
|
|
||||||
return (P && typeof P.h20_1 === 'number') ? P.h20_1 : null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 「栅栏类」= 静态几何中的**立面三角形**:
|
// 「栅栏类」= 静态几何中的**立面三角形**(全部用局部坐标判定,不依赖世界坐标):
|
||||||
// · 必须是三角形(type 8)—— 非三角形静态体(type 1/4 等)是地面/地形代理,跳过会导致掉出地图
|
// · type 4 先解包到真实形状,必须是三角形
|
||||||
// · 最高点高于车体中心 1m(地面/缓坡不满足)
|
// · |法线 z| < 0.6 → 竖直立面(地面法线≈1)
|
||||||
// · |法线 z| < 0.6(竖直立面)
|
// · 竖直跨度 > 100 单位 → 有高度的墙/栅栏(地面/缓坡跨度≈0)
|
||||||
function IsFenceLike(Shape) {
|
function IsFenceLike(Shape) {
|
||||||
if (!IsStaticShape(Shape)) return false;
|
if (!IsStaticShape(Shape)) return false;
|
||||||
if (!IsTriangle(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);
|
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 共用同一套判定)
|
// 本车形状 / 本车与栅栏形状的配对(q9q 与 x9o 共用同一套判定)
|
||||||
@@ -227,6 +216,12 @@
|
|||||||
|
|
||||||
function ShapePoint(Shape) {
|
function ShapePoint(Shape) {
|
||||||
if (!Shape) return null;
|
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);
|
var S = UnwrapShape(Shape);
|
||||||
if (S && S[FShapeType] === TRIANGLE_TYPE) {
|
if (S && S[FShapeType] === TRIANGLE_TYPE) {
|
||||||
var A = S[FV0], B = S[FV1], C = S[FV2];
|
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
|
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;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -291,14 +280,20 @@
|
|||||||
var Type = Shape[FShapeType];
|
var Type = Shape[FShapeType];
|
||||||
var Tri = IsTriangle(Shape);
|
var Tri = IsTriangle(Shape);
|
||||||
var Nz = TriangleNormalZ(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;
|
if (FenceSampleKeys[Key]) return;
|
||||||
FenceSampleKeys[Key] = 1;
|
FenceSampleKeys[Key] = 1;
|
||||||
|
|
||||||
var Pt = ShapePoint(Shape);
|
var Pt = ShapePoint(Shape);
|
||||||
var Near = FindNearNodeNames(Pt, 700);
|
var Near = FindNearNodeNames(Pt, 700);
|
||||||
console.log('[忽略][重叠物体] cat=' + Cat + ' type=' + Type + ' 三角=' + Tri +
|
console.log('[忽略][重叠物体] cat=' + Cat + ' type=' + Type + ' 解包type=' + BaseType +
|
||||||
' nz=' + (Nz === null ? '-' : Nz.toFixed(2)) +
|
' 三角=' + 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) + ')') : '-') +
|
' 位置=' + (Pt ? ('(' + Pt.x.toFixed(0) + ',' + Pt.y.toFixed(0) + ',' + Pt.z.toFixed(0) + ')') : '-') +
|
||||||
' 近邻节点=[' + Near.join(', ') + ']' +
|
' 近邻节点=[' + Near.join(', ') + ']' +
|
||||||
' 当前判定=' + (IsFenceLike(Shape) ? '忽略' : '保留'));
|
' 当前判定=' + (IsFenceLike(Shape) ? '忽略' : '保留'));
|
||||||
|
|||||||
Reference in new issue
Block a user