C++问题:Float数组在大索引位置后无法存储有效值
问题分析与解决方案
看起来你遇到的是数组越界导致内存覆盖的典型C/C++隐蔽bug,这也是你看到法线后半段全为0的核心原因。
核心问题:flagVertices数组容量不足,越界写入覆盖normals
先算清楚内存需求:
- 你的双层循环每轮(i,j)会生成2个三角形,每个三角形含3个顶点,每个顶点存x/y/z三个分量——所以每轮循环要占用
3*3*2 = 18个float位置。 - 但你定义的
flagVertices大小是N*N*VALS_PER_VERT*VERTICES_PER_QUAD,如果VALS_PER_VERT=3(对应顶点的3个分量)、VERTICES_PER_QUAD=4(四边形的4个顶点),总容量只有N*N*3*4=12N²,远小于实际需要的18N²。
当flagVertices被写满后,后续的顶点数据会溢出到栈上相邻的内存区域——也就是你的normals数组。这就导致刚计算好存入normals的法线,立刻被越界写入的顶点数据覆盖成0(或其他顶点值),读取时自然只能看到无效的0值。
修复步骤
修正数组大小匹配实际需求
因为你每个四边形用了6个重复顶点(而非优化后的4个),所以VERTICES_PER_QUAD应该设为6,修改数组定义:// 每个四边形6个顶点,每个顶点3个分量,大小刚好匹配实际需求 float flagVertices[ N*N*VALS_PER_VERT*6 ]; // 法线数组大小同步调整,你的代码每轮存2组法线(每组3分量),总容量完全足够 float normals[ N*N*VALS_PER_VERT*6 ];或者直接用准确的计算式定义:
N*N*2*3*3(N*N个四边形 × 每个2三角形 × 每个3顶点 × 每个3分量)。可选优化:复用顶点减少内存浪费
你当前代码重复存储了大量顶点(比如(1,1)和(0,0)在两个三角形中都存了两次),可以改用顶点索引缓冲(EBO)复用顶点,这样flagVertices的大小可以缩减为(N+1)*(N+1)*3(只存储所有唯一的网格顶点),同时法线也可以对应每个顶点计算,既节省内存又更符合图形学的常规做法。
快速验证方法
你可以在循环中加入简单的越界检查,比如每次idxFlag自增后,打印它的值和数组总容量,当idxFlag超过数组长度时触发提示,就能直观确认是否是越界问题。
内容的提问来源于stack exchange,提问作者HypoFreak
相关产品推荐
相关产品推荐

