对于经常出现的那个问题一个解决方案#

Data: 2025-12-02 23:52:40

绝对解决:

后续可以使用一下。

//---- 绝对防御版矩阵处理代码 ----------------------------------------------------

            // 定义一个安全的默认矩阵 (单位矩阵)
            const IDENTITY_MATRIX = new Float32Array([1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1]);

            // 内部函数:绝对安全的矩阵上传
            // 策略:无论发生什么,绝不 throw Error,遇到问题就用 Identity 顶替,保证画面不崩
            function safeUniformMatrix(gl, location, mat) {
              let data = IDENTITY_MATRIX;
              
              if (mat) {
                // 1. 尝试获取 float32 数组
                let arr = null;
                try {
                    // 如果 mat 本身就是 DOMMatrix,它有 toFloat32Array
                    if (mat.toFloat32Array) arr = mat.toFloat32Array();
                    // 如果 mat 已经是数组
                    else if (mat.length) arr = mat;
                } catch (e) {
                    // console.warn("矩阵转换失败,使用默认值");
                }

                // 2. 只有当数组存在,且长度正确,且没有任何 NaN/Infinity 时,才使用它
                // 注意:检查 !Number.isFinite 是核心,它能同时拦截 NaN 和 Infinity
                if (arr && arr.length === 16 && !arr.some(v => !Number.isFinite(v))) {
                    data = arr;
                } else {
                   // 可以在这里加一个计数器,只 log 前 5 次,避免刷屏
                   if (!W._nanWarned) { 
                       console.warn("捕获到 NaN 矩阵,已自动修复为单位矩阵,防止崩溃。", object.n);
                       W._nanWarned = true; // 每一帧只报一次或者全局只报一次
                   }
                }
              }

              // 3. 执行上传,此时 data 必然是干净的 Float32Array
              gl.uniformMatrix4fv(location, false, data);
            }

            if (!just_compute) {
              // 获取原始矩阵
              let rawMatrix = W.next?.[object.n]?.M || W.next?.[object.n]?.m;
              
              // 构建 safeMat (DOMMatrix 对象)
              let safeMat;
              try {
                  safeMat = new DOMMatrix(rawMatrix);
                  // 立即检查生成出来的矩阵是否含有 NaN (DOMMatrix 构造函数有时不报错但会生成 NaN)
                  if (isNaN(safeMat.m11) || isNaN(safeMat.m41)) {
                      throw new Error("NaN detected");
                  }
              } catch (e) {
                  // 如果原始数据坏了,创建一个干净的单位矩阵,让物体哪怕位置不对,也不要报错
                  safeMat = new DOMMatrix(); 
                  // 甚至可以考虑把坏掉的数据重置,实现“自愈”
                  if(W.next[object.n]) W.next[object.n].m = safeMat; 
              }

              // 上传模型矩阵 M
              safeUniformMatrix(W.gl, W.uniformLocations.m, safeMat);

              // 计算并上传逆矩阵 IM
              let invMat;
              try {
                // invertSelf 可能会在矩阵不可逆(如缩放为0)时抛出错误或产生 NaN
                // 这里我们克隆一个新的矩阵去求逆,避免污染 safeMat
                invMat = DOMMatrix.fromFloat32Array(safeMat.toFloat32Array());
                invMat.invertSelf();
              } catch (e) {
                invMat = new DOMMatrix(); // 求逆失败,回退到单位矩阵
              }
              safeUniformMatrix(W.gl, W.uniformLocations.im, invMat);
            }
            
            //------------------------------------------------------------------------------------

- end -#

© 2025 –   海牧羽工厂 HMY Factory