diff --git a/3dtank.com/play/static/js/unpacked/hornet_bundle.js b/3dtank.com/play/static/js/unpacked/hornet_bundle.js index 3e53f2f..d4bf441 100644 --- a/3dtank.com/play/static/js/unpacked/hornet_bundle.js +++ b/3dtank.com/play/static/js/unpacked/hornet_bundle.js @@ -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 }; diff --git a/3dtank_bundle.js b/3dtank_bundle.js index 3e53f2f..d4bf441 100644 --- a/3dtank_bundle.js +++ b/3dtank_bundle.js @@ -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 }; diff --git a/tools/hornet_3d_wireframe.js b/tools/hornet_3d_wireframe.js index 145dd8a..521fce3 100644 --- a/tools/hornet_3d_wireframe.js +++ b/tools/hornet_3d_wireframe.js @@ -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 };