英文:
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 
colorattribute for each geometry before merging them. - Use 
meshwith the merged geometry as a parameter. Give a material as a child and activate thevertexColorsproperties. 
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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。



评论