From 526adc760c188881289df3e6b714152a99a8e32c Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Mon, 19 Oct 2026 21:45:54 +0800 Subject: [PATCH] =?UTF-8?q?fix(wireframe):=20=E9=A1=B6=E7=82=B9/=E7=B4=A2?= =?UTF-8?q?=E5=BC=95=E4=BC=98=E5=85=88=E8=AF=BB=20CPU=20=E7=AB=AF=E7=BC=93?= =?UTF-8?q?=E5=86=B2=E5=8C=BA=EF=BC=8C=E4=BF=AE=E5=A4=8D=E6=9C=AA=E4=B8=8A?= =?UTF-8?q?=E4=BC=A0=20mesh=20=E9=87=87=E9=9B=86=E5=A4=B1=E8=B4=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../play/static/js/unpacked/hornet_bundle.js | 37 +++++++++++++++++++ 3dtank_bundle.js | 37 +++++++++++++++++++ tools/hornet_3d_wireframe.js | 37 +++++++++++++++++++ 3 files changed, 111 insertions(+) diff --git a/3dtank.com/play/static/js/unpacked/hornet_bundle.js b/3dtank.com/play/static/js/unpacked/hornet_bundle.js index 0e91cf7..26df6b8 100644 --- a/3dtank.com/play/static/js/unpacked/hornet_bundle.js +++ b/3dtank.com/play/static/js/unpacked/hornet_bundle.js @@ -1825,12 +1825,45 @@ return (Dev && Dev.f75_1) ? Dev.f75_1 : null; } + // 把引擎的 CPU 端缓冲区包装转成 TypedArray + // J$.x3x_1 / Y$.p3x_1 = 未上传时的原始数据(上传后置 null) + // 包装接口:v2u()=底层视图,g2t()=元素偏移,t2t()=元素个数 + function ToTypedArray(Src, Kind) { + if (!Src) return null; + try { + if (typeof Src.v2u === 'function') { + var V = Src.v2u(); + var Start = typeof Src.g2t === 'function' ? Src.g2t() : 0; + var Count = typeof Src.t2t === 'function' ? Src.t2t() : (V && V.length); + if (ArrayBuffer.isView(V) && Count > 0) { + var ByteOff = V.byteOffset + Start * V.BYTES_PER_ELEMENT; + if (Kind === 'u32') return new Uint32Array(V.buffer, ByteOff, Count); + if (Kind === 'u16') return new Uint16Array(V.buffer, ByteOff, Count); + return new Float32Array(V.buffer, ByteOff, Count); + } + } + if (ArrayBuffer.isView(Src)) { + if (Kind === 'u16') return (Src instanceof Uint16Array) ? Src : new Uint16Array(Src.buffer, Src.byteOffset, Src.byteLength >> 1); + if (Kind === 'u32') return (Src instanceof Uint32Array) ? Src : new Uint32Array(Src.buffer, Src.byteOffset, Src.byteLength >> 2); + return (Src instanceof Float32Array) ? Src : new Float32Array(Src.buffer, Src.byteOffset, Src.byteLength >> 2); + } + if (typeof Src.length === 'number' && Src.length > 0) { + return (Kind === 'u16') ? Uint16Array.from(Src) : (Kind === 'u32' ? Uint32Array.from(Src) : Float32Array.from(Src)); + } + } catch (e) {} + return null; + } + function ReadVertexPositionsFromTp(tp) { 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; + // ① 优先 CPU 端原始数据:未上传 GPU 的 mesh 也能读到(v3x_1.d75_1 此时为 null) + var Cpu = ToTypedArray(Buf.x3x_1, 'f32'); + if (Cpu && Cpu.length) return Cpu; + // ② GPU 回读(引擎已上传并释放 CPU 数据时) var gl = GetGlFromResource(Buf); var webglBuf = Buf.v3x_1 && Buf.v3x_1.d75_1; if (!gl || !webglBuf) return null; @@ -1854,6 +1887,10 @@ if (!il) continue; var IdxBuf = il.q4w_1 || il.u3p_1; if (!IdxBuf) continue; + // ① CPU 端索引数据(Y$.p3x_1),未上传时也能用 + var Cpu = ToTypedArray(IdxBuf.p3x_1, 'u16'); + if (Cpu && Cpu.length) { allIndices.push(Cpu); continue; } + // ② GPU 回读 var gl = GetGlFromResource(IdxBuf); var webglBuf = IdxBuf.n3x_1 && IdxBuf.n3x_1.d75_1; if (!gl || !webglBuf) continue; diff --git a/3dtank_bundle.js b/3dtank_bundle.js index 0e91cf7..26df6b8 100644 --- a/3dtank_bundle.js +++ b/3dtank_bundle.js @@ -1825,12 +1825,45 @@ return (Dev && Dev.f75_1) ? Dev.f75_1 : null; } + // 把引擎的 CPU 端缓冲区包装转成 TypedArray + // J$.x3x_1 / Y$.p3x_1 = 未上传时的原始数据(上传后置 null) + // 包装接口:v2u()=底层视图,g2t()=元素偏移,t2t()=元素个数 + function ToTypedArray(Src, Kind) { + if (!Src) return null; + try { + if (typeof Src.v2u === 'function') { + var V = Src.v2u(); + var Start = typeof Src.g2t === 'function' ? Src.g2t() : 0; + var Count = typeof Src.t2t === 'function' ? Src.t2t() : (V && V.length); + if (ArrayBuffer.isView(V) && Count > 0) { + var ByteOff = V.byteOffset + Start * V.BYTES_PER_ELEMENT; + if (Kind === 'u32') return new Uint32Array(V.buffer, ByteOff, Count); + if (Kind === 'u16') return new Uint16Array(V.buffer, ByteOff, Count); + return new Float32Array(V.buffer, ByteOff, Count); + } + } + if (ArrayBuffer.isView(Src)) { + if (Kind === 'u16') return (Src instanceof Uint16Array) ? Src : new Uint16Array(Src.buffer, Src.byteOffset, Src.byteLength >> 1); + if (Kind === 'u32') return (Src instanceof Uint32Array) ? Src : new Uint32Array(Src.buffer, Src.byteOffset, Src.byteLength >> 2); + return (Src instanceof Float32Array) ? Src : new Float32Array(Src.buffer, Src.byteOffset, Src.byteLength >> 2); + } + if (typeof Src.length === 'number' && Src.length > 0) { + return (Kind === 'u16') ? Uint16Array.from(Src) : (Kind === 'u32' ? Uint32Array.from(Src) : Float32Array.from(Src)); + } + } catch (e) {} + return null; + } + function ReadVertexPositionsFromTp(tp) { 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; + // ① 优先 CPU 端原始数据:未上传 GPU 的 mesh 也能读到(v3x_1.d75_1 此时为 null) + var Cpu = ToTypedArray(Buf.x3x_1, 'f32'); + if (Cpu && Cpu.length) return Cpu; + // ② GPU 回读(引擎已上传并释放 CPU 数据时) var gl = GetGlFromResource(Buf); var webglBuf = Buf.v3x_1 && Buf.v3x_1.d75_1; if (!gl || !webglBuf) return null; @@ -1854,6 +1887,10 @@ if (!il) continue; var IdxBuf = il.q4w_1 || il.u3p_1; if (!IdxBuf) continue; + // ① CPU 端索引数据(Y$.p3x_1),未上传时也能用 + var Cpu = ToTypedArray(IdxBuf.p3x_1, 'u16'); + if (Cpu && Cpu.length) { allIndices.push(Cpu); continue; } + // ② GPU 回读 var gl = GetGlFromResource(IdxBuf); var webglBuf = IdxBuf.n3x_1 && IdxBuf.n3x_1.d75_1; if (!gl || !webglBuf) continue; diff --git a/tools/hornet_3d_wireframe.js b/tools/hornet_3d_wireframe.js index aa1e4ee..944a986 100644 --- a/tools/hornet_3d_wireframe.js +++ b/tools/hornet_3d_wireframe.js @@ -300,12 +300,45 @@ return (Dev && Dev.f75_1) ? Dev.f75_1 : null; } + // 把引擎的 CPU 端缓冲区包装转成 TypedArray + // J$.x3x_1 / Y$.p3x_1 = 未上传时的原始数据(上传后置 null) + // 包装接口:v2u()=底层视图,g2t()=元素偏移,t2t()=元素个数 + function ToTypedArray(Src, Kind) { + if (!Src) return null; + try { + if (typeof Src.v2u === 'function') { + var V = Src.v2u(); + var Start = typeof Src.g2t === 'function' ? Src.g2t() : 0; + var Count = typeof Src.t2t === 'function' ? Src.t2t() : (V && V.length); + if (ArrayBuffer.isView(V) && Count > 0) { + var ByteOff = V.byteOffset + Start * V.BYTES_PER_ELEMENT; + if (Kind === 'u32') return new Uint32Array(V.buffer, ByteOff, Count); + if (Kind === 'u16') return new Uint16Array(V.buffer, ByteOff, Count); + return new Float32Array(V.buffer, ByteOff, Count); + } + } + if (ArrayBuffer.isView(Src)) { + if (Kind === 'u16') return (Src instanceof Uint16Array) ? Src : new Uint16Array(Src.buffer, Src.byteOffset, Src.byteLength >> 1); + if (Kind === 'u32') return (Src instanceof Uint32Array) ? Src : new Uint32Array(Src.buffer, Src.byteOffset, Src.byteLength >> 2); + return (Src instanceof Float32Array) ? Src : new Float32Array(Src.buffer, Src.byteOffset, Src.byteLength >> 2); + } + if (typeof Src.length === 'number' && Src.length > 0) { + return (Kind === 'u16') ? Uint16Array.from(Src) : (Kind === 'u32' ? Uint32Array.from(Src) : Float32Array.from(Src)); + } + } catch (e) {} + return null; + } + function ReadVertexPositionsFromTp(tp) { 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; + // ① 优先 CPU 端原始数据:未上传 GPU 的 mesh 也能读到(v3x_1.d75_1 此时为 null) + var Cpu = ToTypedArray(Buf.x3x_1, 'f32'); + if (Cpu && Cpu.length) return Cpu; + // ② GPU 回读(引擎已上传并释放 CPU 数据时) var gl = GetGlFromResource(Buf); var webglBuf = Buf.v3x_1 && Buf.v3x_1.d75_1; if (!gl || !webglBuf) return null; @@ -329,6 +362,10 @@ if (!il) continue; var IdxBuf = il.q4w_1 || il.u3p_1; if (!IdxBuf) continue; + // ① CPU 端索引数据(Y$.p3x_1),未上传时也能用 + var Cpu = ToTypedArray(IdxBuf.p3x_1, 'u16'); + if (Cpu && Cpu.length) { allIndices.push(Cpu); continue; } + // ② GPU 回读 var gl = GetGlFromResource(IdxBuf); var webglBuf = IdxBuf.n3x_1 && IdxBuf.n3x_1.d75_1; if (!gl || !webglBuf) continue;