fix(wireframe): GPU 顶点/索引缓冲字段按新版重定位,恢复模型采集

This commit is contained in:
TermiNexus committed 2026-10-18 19:37:43 +08:00
1 parent 86b9322a9f
commit dcf9a57456
3 files changed
+192 -81

No files matched your search

@@ -1751,10 +1751,28 @@
// 皮肤对象.g17r_1 = 车身部件表;每个部件 part.j17r_1 是**单个 BP 节点**(旧版是节点列表)。
// 炮塔根节点 = skinComp.a17q_1(weaponSkin 组件 LUt.u11p() = e13a().a17q_1,e13a 取的就是 skin 组件)。
// 旧写法(w14w_1 / n11c_1 / m17a_1)在新版已被无关类占用(w14w_1=SetReverseBackTurn、m17a_1=数值参数),不再可用。
var SkinCompCache = new WeakMap();
function GetSkinComponent(entity) {
if (!entity) return null;
var Cached = SkinCompCache.get(entity);
if (Cached) return Cached;
var comp = FindComponentByField(entity, 'g159_1');
if (comp) return comp;
comp = FindComponentByField(entity, 'a17q_1');
if (!comp) comp = FindComponentByField(entity, 'a17q_1');
// 兜底:按结构找 —— 组件字段值是"皮肤对象"(含 g17r_1 部件表)
if (!comp) {
try {
entity.qz1_1.s2a_1.forEach(function (VL) {
if (comp) return;
var C = (VL && typeof VL.g1 === 'function') ? VL.g1(0) : VL;
if (!C) return;
for (var K in C) {
var V = C[K];
if (V && typeof V === 'object' && V.g17r_1 && typeof V.g17r_1.e1 === 'function') { comp = C; return; }
}
});
} catch (e) {}
}
if (comp) SkinCompCache.set(entity, comp);
return comp;
}
@@ -1788,17 +1806,27 @@
} catch (e) {}
}
// ===== 从GPU读取顶点位置数据(缓冲区[0]) =====
// ===== 从GPU读取顶点位置数据(新版结构) =====
// 新旧差异(main.7cfa4058):
// Tp(类 sm): x4w_1 = 顶点组列表,每组 { h3x_1: 顶点缓冲资源 J$, i3x_1: 属性布局 }
// J$: v3x_1 = GPU 缓冲包装(kC,d75_1 = 原生 WebGLBuffer),w3x_1 = 顶点数
// 设备:V$.s3h_1 = GL 包装器 $C,$C.f75_1 = 原生 WebGL2RenderingContext
// ⚠ 旧字段 d3x_1 / s3h_1.b74_1 / v3x_1.z73_1 在新版分别是"渲染参数 / 雾色 uniform / uniform 槽位",全错
function GetGlFromResource(Res) {
if (!Res) return null;
var Dev = Res.s3h_1;
return (Dev && Dev.f75_1) ? Dev.f75_1 : null;
}
function ReadVertexPositionsFromTp(tp) {
if (!tp || !tp.x4w_1) return null;
var tl = tp.x4w_1.g1(0);
if (!tl || !tl.d3x_1) return null;
var vq = tl.d3x_1;
var bs = vq.s3h_1;
if (!bs || !bs.b74_1) return null;
var gl = bs.b74_1;
var webglBuf = vq.v3x_1 && vq.v3x_1.z73_1;
if (!webglBuf) return null;
if (!tp || !tp.x4w_1 || typeof tp.x4w_1.e1 !== 'function' || tp.x4w_1.e1() === 0) return null;
var group = tp.x4w_1.g1(0);
if (!group) return null;
var Buf = group.h3x_1; // J$
if (!Buf) return null;
var gl = GetGlFromResource(Buf);
var webglBuf = Buf.v3x_1 && Buf.v3x_1.d75_1;
if (!gl || !webglBuf) return null;
gl.bindBuffer(gl.ARRAY_BUFFER, webglBuf);
var bufSize = gl.getBufferParameter(gl.ARRAY_BUFFER, gl.BUFFER_SIZE);
if (bufSize <= 0) return null;
@@ -1808,6 +1836,7 @@
}
// ===== 从GPU读取索引数据 =====
// y4w_1 = 索引列表,每项 { q4w_1: 索引缓冲资源 Y$ }(旧版是 il.u3p_1)
function ReadIndicesFromTp(tp) {
if (!tp.y4w_1 || typeof tp.y4w_1.e1 !== 'function') return null;
var meshCount = tp.y4w_1.e1();
@@ -1815,13 +1844,12 @@
var allIndices = [];
for (var m = 0; m < meshCount; m++) {
var il = tp.y4w_1.g1(m);
if (!il || !il.u3p_1) continue;
var fq = il.u3p_1;
var bs = fq.s3h_1;
if (!bs || !bs.b74_1) continue;
var gl = bs.b74_1;
var webglBuf = fq.n3x_1 && fq.n3x_1.z73_1;
if (!webglBuf) continue;
if (!il) continue;
var IdxBuf = il.q4w_1 || il.u3p_1;
if (!IdxBuf) continue;
var gl = GetGlFromResource(IdxBuf);
var webglBuf = IdxBuf.n3x_1 && IdxBuf.n3x_1.d75_1;
if (!gl || !webglBuf) continue;
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, webglBuf);
var bufSize = gl.getBufferParameter(gl.ELEMENT_ARRAY_BUFFER, gl.BUFFER_SIZE);
if (bufSize <= 0) continue;
@@ -1852,14 +1880,23 @@
if (idxArr[j] > maxIdx) maxIdx = idxArr[j];
}
}
var stride = 3;
var vc3 = Math.floor(positions.length / 3);
if (maxIdx >= vc3) {
// stride=3 顶点数不够,尝试常见 interleaved 布局
var candidates = [8, 11, 5, 7, 14];
for (var c = 0; c < candidates.length; c++) {
var vc = Math.floor(positions.length / candidates[c]);
if (maxIdx < vc) { stride = candidates[c]; break; }
var stride = 0;
// 优先用引擎记录的顶点数反推 stride(J$.w3x_1 = 顶点数)
try {
var G0 = tp.x4w_1.g1(0);
var Vc = G0 && G0.h3x_1 && G0.h3x_1.w3x_1;
if (Vc > 0 && positions.length % Vc === 0) stride = Math.round(positions.length / Vc);
} catch (e) {}
if (!stride || stride < 3 || stride > 20) {
stride = 3;
var vc3 = Math.floor(positions.length / 3);
if (maxIdx >= vc3) {
// stride=3 顶点数不够,尝试常见 interleaved 布局
var candidates = [8, 11, 5, 7, 14];
for (var c = 0; c < candidates.length; c++) {
var vc = Math.floor(positions.length / candidates[c]);
if (maxIdx < vc) { stride = candidates[c]; break; }
}
}
}
var data = { positions: positions, indices: indices, stride: stride };
+64 -27
View File
@@ -1751,10 +1751,28 @@
// 皮肤对象.g17r_1 = 车身部件表;每个部件 part.j17r_1 是**单个 BP 节点**(旧版是节点列表)。
// 炮塔根节点 = skinComp.a17q_1(weaponSkin 组件 LUt.u11p() = e13a().a17q_1,e13a 取的就是 skin 组件)。
// 旧写法(w14w_1 / n11c_1 / m17a_1)在新版已被无关类占用(w14w_1=SetReverseBackTurn、m17a_1=数值参数),不再可用。
var SkinCompCache = new WeakMap();
function GetSkinComponent(entity) {
if (!entity) return null;
var Cached = SkinCompCache.get(entity);
if (Cached) return Cached;
var comp = FindComponentByField(entity, 'g159_1');
if (comp) return comp;
comp = FindComponentByField(entity, 'a17q_1');
if (!comp) comp = FindComponentByField(entity, 'a17q_1');
// 兜底:按结构找 —— 组件字段值是"皮肤对象"(含 g17r_1 部件表)
if (!comp) {
try {
entity.qz1_1.s2a_1.forEach(function (VL) {
if (comp) return;
var C = (VL && typeof VL.g1 === 'function') ? VL.g1(0) : VL;
if (!C) return;
for (var K in C) {
var V = C[K];
if (V && typeof V === 'object' && V.g17r_1 && typeof V.g17r_1.e1 === 'function') { comp = C; return; }
}
});
} catch (e) {}
}
if (comp) SkinCompCache.set(entity, comp);
return comp;
}
@@ -1788,17 +1806,27 @@
} catch (e) {}
}
// ===== 从GPU读取顶点位置数据(缓冲区[0]) =====
// ===== 从GPU读取顶点位置数据(新版结构) =====
// 新旧差异(main.7cfa4058):
// Tp(类 sm): x4w_1 = 顶点组列表,每组 { h3x_1: 顶点缓冲资源 J$, i3x_1: 属性布局 }
// J$: v3x_1 = GPU 缓冲包装(kC,d75_1 = 原生 WebGLBuffer),w3x_1 = 顶点数
// 设备:V$.s3h_1 = GL 包装器 $C,$C.f75_1 = 原生 WebGL2RenderingContext
// ⚠ 旧字段 d3x_1 / s3h_1.b74_1 / v3x_1.z73_1 在新版分别是"渲染参数 / 雾色 uniform / uniform 槽位",全错
function GetGlFromResource(Res) {
if (!Res) return null;
var Dev = Res.s3h_1;
return (Dev && Dev.f75_1) ? Dev.f75_1 : null;
}
function ReadVertexPositionsFromTp(tp) {
if (!tp || !tp.x4w_1) return null;
var tl = tp.x4w_1.g1(0);
if (!tl || !tl.d3x_1) return null;
var vq = tl.d3x_1;
var bs = vq.s3h_1;
if (!bs || !bs.b74_1) return null;
var gl = bs.b74_1;
var webglBuf = vq.v3x_1 && vq.v3x_1.z73_1;
if (!webglBuf) return null;
if (!tp || !tp.x4w_1 || typeof tp.x4w_1.e1 !== 'function' || tp.x4w_1.e1() === 0) return null;
var group = tp.x4w_1.g1(0);
if (!group) return null;
var Buf = group.h3x_1; // J$
if (!Buf) return null;
var gl = GetGlFromResource(Buf);
var webglBuf = Buf.v3x_1 && Buf.v3x_1.d75_1;
if (!gl || !webglBuf) return null;
gl.bindBuffer(gl.ARRAY_BUFFER, webglBuf);
var bufSize = gl.getBufferParameter(gl.ARRAY_BUFFER, gl.BUFFER_SIZE);
if (bufSize <= 0) return null;
@@ -1808,6 +1836,7 @@
}
// ===== 从GPU读取索引数据 =====
// y4w_1 = 索引列表,每项 { q4w_1: 索引缓冲资源 Y$ }(旧版是 il.u3p_1)
function ReadIndicesFromTp(tp) {
if (!tp.y4w_1 || typeof tp.y4w_1.e1 !== 'function') return null;
var meshCount = tp.y4w_1.e1();
@@ -1815,13 +1844,12 @@
var allIndices = [];
for (var m = 0; m < meshCount; m++) {
var il = tp.y4w_1.g1(m);
if (!il || !il.u3p_1) continue;
var fq = il.u3p_1;
var bs = fq.s3h_1;
if (!bs || !bs.b74_1) continue;
var gl = bs.b74_1;
var webglBuf = fq.n3x_1 && fq.n3x_1.z73_1;
if (!webglBuf) continue;
if (!il) continue;
var IdxBuf = il.q4w_1 || il.u3p_1;
if (!IdxBuf) continue;
var gl = GetGlFromResource(IdxBuf);
var webglBuf = IdxBuf.n3x_1 && IdxBuf.n3x_1.d75_1;
if (!gl || !webglBuf) continue;
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, webglBuf);
var bufSize = gl.getBufferParameter(gl.ELEMENT_ARRAY_BUFFER, gl.BUFFER_SIZE);
if (bufSize <= 0) continue;
@@ -1852,14 +1880,23 @@
if (idxArr[j] > maxIdx) maxIdx = idxArr[j];
}
}
var stride = 3;
var vc3 = Math.floor(positions.length / 3);
if (maxIdx >= vc3) {
// stride=3 顶点数不够,尝试常见 interleaved 布局
var candidates = [8, 11, 5, 7, 14];
for (var c = 0; c < candidates.length; c++) {
var vc = Math.floor(positions.length / candidates[c]);
if (maxIdx < vc) { stride = candidates[c]; break; }
var stride = 0;
// 优先用引擎记录的顶点数反推 stride(J$.w3x_1 = 顶点数)
try {
var G0 = tp.x4w_1.g1(0);
var Vc = G0 && G0.h3x_1 && G0.h3x_1.w3x_1;
if (Vc > 0 && positions.length % Vc === 0) stride = Math.round(positions.length / Vc);
} catch (e) {}
if (!stride || stride < 3 || stride > 20) {
stride = 3;
var vc3 = Math.floor(positions.length / 3);
if (maxIdx >= vc3) {
// stride=3 顶点数不够,尝试常见 interleaved 布局
var candidates = [8, 11, 5, 7, 14];
for (var c = 0; c < candidates.length; c++) {
var vc = Math.floor(positions.length / candidates[c]);
if (maxIdx < vc) { stride = candidates[c]; break; }
}
}
}
var data = { positions: positions, indices: indices, stride: stride };
+64 -27
View File
@@ -226,10 +226,28 @@
// 皮肤对象.g17r_1 = 车身部件表;每个部件 part.j17r_1 是**单个 BP 节点**(旧版是节点列表)。
// 炮塔根节点 = skinComp.a17q_1(weaponSkin 组件 LUt.u11p() = e13a().a17q_1,e13a 取的就是 skin 组件)。
// 旧写法(w14w_1 / n11c_1 / m17a_1)在新版已被无关类占用(w14w_1=SetReverseBackTurn、m17a_1=数值参数),不再可用。
var SkinCompCache = new WeakMap();
function GetSkinComponent(entity) {
if (!entity) return null;
var Cached = SkinCompCache.get(entity);
if (Cached) return Cached;
var comp = FindComponentByField(entity, 'g159_1');
if (comp) return comp;
comp = FindComponentByField(entity, 'a17q_1');
if (!comp) comp = FindComponentByField(entity, 'a17q_1');
// 兜底:按结构找 —— 组件字段值是"皮肤对象"(含 g17r_1 部件表)
if (!comp) {
try {
entity.qz1_1.s2a_1.forEach(function (VL) {
if (comp) return;
var C = (VL && typeof VL.g1 === 'function') ? VL.g1(0) : VL;
if (!C) return;
for (var K in C) {
var V = C[K];
if (V && typeof V === 'object' && V.g17r_1 && typeof V.g17r_1.e1 === 'function') { comp = C; return; }
}
});
} catch (e) {}
}
if (comp) SkinCompCache.set(entity, comp);
return comp;
}
@@ -263,17 +281,27 @@
} catch (e) {}
}
// ===== 从GPU读取顶点位置数据(缓冲区[0]) =====
// ===== 从GPU读取顶点位置数据(新版结构) =====
// 新旧差异(main.7cfa4058):
// Tp(类 sm): x4w_1 = 顶点组列表,每组 { h3x_1: 顶点缓冲资源 J$, i3x_1: 属性布局 }
// J$: v3x_1 = GPU 缓冲包装(kC,d75_1 = 原生 WebGLBuffer),w3x_1 = 顶点数
// 设备:V$.s3h_1 = GL 包装器 $C,$C.f75_1 = 原生 WebGL2RenderingContext
// ⚠ 旧字段 d3x_1 / s3h_1.b74_1 / v3x_1.z73_1 在新版分别是"渲染参数 / 雾色 uniform / uniform 槽位",全错
function GetGlFromResource(Res) {
if (!Res) return null;
var Dev = Res.s3h_1;
return (Dev && Dev.f75_1) ? Dev.f75_1 : null;
}
function ReadVertexPositionsFromTp(tp) {
if (!tp || !tp.x4w_1) return null;
var tl = tp.x4w_1.g1(0);
if (!tl || !tl.d3x_1) return null;
var vq = tl.d3x_1;
var bs = vq.s3h_1;
if (!bs || !bs.b74_1) return null;
var gl = bs.b74_1;
var webglBuf = vq.v3x_1 && vq.v3x_1.z73_1;
if (!webglBuf) return null;
if (!tp || !tp.x4w_1 || typeof tp.x4w_1.e1 !== 'function' || tp.x4w_1.e1() === 0) return null;
var group = tp.x4w_1.g1(0);
if (!group) return null;
var Buf = group.h3x_1; // J$
if (!Buf) return null;
var gl = GetGlFromResource(Buf);
var webglBuf = Buf.v3x_1 && Buf.v3x_1.d75_1;
if (!gl || !webglBuf) return null;
gl.bindBuffer(gl.ARRAY_BUFFER, webglBuf);
var bufSize = gl.getBufferParameter(gl.ARRAY_BUFFER, gl.BUFFER_SIZE);
if (bufSize <= 0) return null;
@@ -283,6 +311,7 @@
}
// ===== 从GPU读取索引数据 =====
// y4w_1 = 索引列表,每项 { q4w_1: 索引缓冲资源 Y$ }(旧版是 il.u3p_1)
function ReadIndicesFromTp(tp) {
if (!tp.y4w_1 || typeof tp.y4w_1.e1 !== 'function') return null;
var meshCount = tp.y4w_1.e1();
@@ -290,13 +319,12 @@
var allIndices = [];
for (var m = 0; m < meshCount; m++) {
var il = tp.y4w_1.g1(m);
if (!il || !il.u3p_1) continue;
var fq = il.u3p_1;
var bs = fq.s3h_1;
if (!bs || !bs.b74_1) continue;
var gl = bs.b74_1;
var webglBuf = fq.n3x_1 && fq.n3x_1.z73_1;
if (!webglBuf) continue;
if (!il) continue;
var IdxBuf = il.q4w_1 || il.u3p_1;
if (!IdxBuf) continue;
var gl = GetGlFromResource(IdxBuf);
var webglBuf = IdxBuf.n3x_1 && IdxBuf.n3x_1.d75_1;
if (!gl || !webglBuf) continue;
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, webglBuf);
var bufSize = gl.getBufferParameter(gl.ELEMENT_ARRAY_BUFFER, gl.BUFFER_SIZE);
if (bufSize <= 0) continue;
@@ -327,14 +355,23 @@
if (idxArr[j] > maxIdx) maxIdx = idxArr[j];
}
}
var stride = 3;
var vc3 = Math.floor(positions.length / 3);
if (maxIdx >= vc3) {
// stride=3 顶点数不够,尝试常见 interleaved 布局
var candidates = [8, 11, 5, 7, 14];
for (var c = 0; c < candidates.length; c++) {
var vc = Math.floor(positions.length / candidates[c]);
if (maxIdx < vc) { stride = candidates[c]; break; }
var stride = 0;
// 优先用引擎记录的顶点数反推 stride(J$.w3x_1 = 顶点数)
try {
var G0 = tp.x4w_1.g1(0);
var Vc = G0 && G0.h3x_1 && G0.h3x_1.w3x_1;
if (Vc > 0 && positions.length % Vc === 0) stride = Math.round(positions.length / Vc);
} catch (e) {}
if (!stride || stride < 3 || stride > 20) {
stride = 3;
var vc3 = Math.floor(positions.length / 3);
if (maxIdx >= vc3) {
// stride=3 顶点数不够,尝试常见 interleaved 布局
var candidates = [8, 11, 5, 7, 14];
for (var c = 0; c < candidates.length; c++) {
var vc = Math.floor(positions.length / candidates[c]);
if (maxIdx < vc) { stride = candidates[c]; break; }
}
}
}
var data = { positions: positions, indices: indices, stride: stride };