如何修改Tess2或使用其他JavaScript库在轮廓三角化生成2D网格时保留颜色数据
我之前做2D图形渲染的时候也碰到过完全一样的需求,给你分享两种可行的方案:一种是修改Tess2源码来实现颜色关联,另一种是用现成的库直接搞定。
一、修改Tess2源码关联颜色数据
Tess2本身没设计颜色关联的逻辑,但它的源码结构很清晰,我们可以给轮廓和最终的三角形加上颜色属性:
1. 扩展轮廓输入结构
原来你传入的轮廓大概是这样的:
const contours = [ { vertices: [x1, y1, x2, y2, ...], winding: Tess2.WINDING_NEGATIVE }, // 实心区域 { vertices: [x3, y3, x4, y4, ...], winding: Tess2.WINDING_POSITIVE } // 孔洞 ];
现在给每个实心轮廓(注意孔洞不需要颜色)加上color字段:
const contours = [ { vertices: [x1, y1, x2, y2, ...], winding: Tess2.WINDING_NEGATIVE, color: '#ff0000' }, { vertices: [x3, y3, x4, y4, ...], winding: Tess2.WINDING_POSITIVE } ];
2. 在Tess2中保存轮廓颜色
找到Tess2源码里的addContour方法(大概在Tesselator类里),修改它的逻辑,把传入的color参数存储到对应的轮廓对象中。比如:
// 原addContour方法可能接收vertices和winding,现在改成接收完整的轮廓对象 addContour(contour) { const { vertices, winding, color } = contour; // 保留原有的顶点、缠绕顺序处理逻辑 // 新增:保存颜色到轮廓数据里 this.contours.push({ vertices, winding, color }); }
3. 给生成的三角形绑定颜色
Tess2最终会生成包含三角形顶点索引的meshes数据。你需要找到源码中构建三角形的部分(比如generateMesh相关逻辑),这里需要跟踪每个三角形所属的实心轮廓。
因为Tess2是根据缠绕顺序区分实心和孔洞的,每个最终的填充三角形必然属于某个WINDING_NEGATIVE的轮廓。如果源码里直接找不到面和轮廓的关联,也可以用简化方法:对每个实心轮廓单独调用Tess2三角化,然后给这个轮廓生成的所有三角形统一赋予该轮廓的颜色。这种方法适合没有重叠布尔运算的场景,实现起来更简单。
二、用现成库直接实现:Earcut + 自定义颜色映射
如果不想改源码,推荐用earcut这个轻量的三角化库,它支持带孔洞的多边形,而且很容易给三角形绑定颜色:
1. 按区域组织轮廓
把每个带颜色的实心轮廓(以及对应的孔洞)作为一个独立的区域,比如:
const regions = [ { color: '#ff0000', outer: [x1, y1, x2, y2, ...], // 实心轮廓点 holes: [[x3, y3, x4, y4, ...]] // 该区域的孔洞 }, { color: '#00ff00', outer: [x5, y5, x6, y6, ...], holes: [] } ];
2. 逐个区域三角化并绑定颜色
对每个区域,用earcut生成三角化索引,然后给每个三角形赋予该区域的颜色:
import earcut from 'earcut'; const coloredTriangles = []; regions.forEach(region => { // 构造earcut需要的输入格式:顶点数组 + 孔洞索引数组 const vertices = [...region.outer]; const holeIndices = region.holes.map(hole => vertices.length); region.holes.forEach(hole => vertices.push(...hole)); // 生成三角化索引 const indices = earcut(vertices, holeIndices); // 把索引转换成三角形,并绑定颜色 for (let i = 0; i < indices.length; i += 3) { coloredTriangles.push({ color: region.color, vertices: [ [vertices[indices[i]*2], vertices[indices[i]*2+1]], [vertices[indices[i+1]*2], vertices[indices[i+1]*2+1]], [vertices[indices[i+2]*2], vertices[indices[i+2]*2+1]] ] }); } });
这样生成的coloredTriangles数组里,每个三角形都带着对应的颜色数据,完全满足你的需求。
补充说明
如果你需要处理复杂的布尔运算(比如多个轮廓重叠后的混合颜色),那可能需要在三角化后额外做区域检测,但大部分场景下,上面两种方法足够解决问题了。
内容的提问来源于stack exchange,提问作者hedgehog90

