英文:
How to merge geometries and keep one color per geometry in R3F
问题
将多个几何形状合并并保留每个几何形状的颜色。
3个合并多边形的示例如下。
英文:
The idea would be to merge several geometries and keep the color for each geometry.
An example with 3 merges polygones would be the following.
答案1
得分: 1
Here's the translated content:
可能的解决方案
- 在合并它们之前为每个几何体设置
color
属性。 - 使用合并后的几何体作为参数来创建
mesh
。作为子元素提供一个材质并激活vertexColors
属性。
示例
假设我们想要合并3个多边形,每个多边形有一种颜色:
// 要显示的多边形
const zones = [{
name: 'zone1',
coords: [[-2,0],[-2,2],[-0.4,1], [-0.8,-1.5]],
color: 0xff0000
},
{
name: 'zone2',
coords: [[-6,0],[-6,2],[-6.4,1], [-6.8,-1.5]],
color: 0x0000ff
},
{
name: 'zone3',
coords: [[4,0],[4,2],[5.6,1], [6.8,-1.5]],
color: 0x0000ff
}]
- 使用属性创建合并后的几何体如下所示:
let geometries = [];
zones.forEach((zone, iZone) => {
const shape = new THREE.Shape();
const coords = zone.coords;
const color = new THREE.Color(zone.color);
const startPoint = coords[0];
// 画出形状
shape.moveTo(startPoint[0], startPoint[1]);
for (let i = 1; i < coords.length; i++) {
shape.lineTo(coords[i][0], coords[i][1]);
}
// 根据形状创建几何体
const geom = new THREE.ShapeGeometry(shape);
// 创建一个与索引长度相同的属性,用于存储颜色状态
const indicesLength = geom.attributes.position.count;
const aColor = new Float32Array(indicesLength * 3);
for (let k = 0; k < aColor.length; k += 3) {
aColor[k] = color.r;
aColor[k + 1] = color.g;
aColor[k + 2] = color.b;
}
geom.setAttribute('color', new THREE.BufferAttribute(aColor, 3));
geometries.push(geom);
})
const newMerged = BufferGeometryUtils.mergeGeometries(geometries)
- 在你的jsx中,你会有以下内容:
<mesh geometry={merged}>
{/* 激活顶点颜色 */}
<meshBasicMaterial vertexColors />
</mesh>
可以在这里找到实现的示例:Codesandbox
英文:
Possible solution
- Set the
color
attribute for each geometry before merging them. - Use
mesh
with the merged geometry as a parameter. Give a material as a child and activate thevertexColors
properties.
EXAMPLE
Let's say we want to merge 3 polygons with one color per polygone:
// Polygones to display
const zones = [{
name:'zone1',
coords:[[-2,0],[-2,2],[-0.4,1], [-0.8,-1.5]],
color: 0xff0000
},
{
name:'zone2',
coords:[[-6,0],[-6,2],[-6.4,1], [-6.8,-1.5]],
color: 0x0000ff
},
{
name:'zone3',
coords:[[4,0],[4,2],[5.6,1], [6.8,-1.5]],
color: 0x0000ff
},
]
- Creating the merged geometry with the attributes would look like this:
let geometries = [];
zones.forEach((zone,iZone) => {
const shape = new THREE.Shape();
const coords = zone.coords;
const color = new THREE.Color(zone.color);
const startPoint = coords[0];
// Draw the shape
shape.moveTo(startPoint[0],startPoint[1]);
for (let i=1;i<coords.length; i++){
shape.lineTo(coords[i][0], coords[i][1]);
}
// Create the geometry thanks to the shape
const geom = new THREE.ShapeGeometry(shape);
// Create an attributes (same length that the indices) that will store the color state
const indicesLength = geom.attributes.position.count;
const aColor = new Float32Array(indicesLength * 3);
for (let k = 0; k < aColor.length; k+=3){
aColor[k] = color.r;
aColor[k+1] = color.g;
aColor[k+2] = color.b;
}
geom.setAttribute('color', new THREE.BufferAttribute(aColor, 3));
geometries.push(geom);
})
const newMerged = BufferGeometryUtils.mergeGeometries(geometries)
- And in your jsx you would have the following:
<mesh geometry={merged}>
{/* activate vertex color */}
<meshBasicMaterial vertexColors/>
</mesh>
An example of the implementation can be found here: Codesandbox
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论