如何合并几何体并保持每个几何体的颜色在R3F中。

huangapple go评论58阅读模式
英文:

How to merge geometries and keep one color per geometry in R3F

问题

将多个几何形状合并并保留每个几何形状的颜色。
3个合并多边形的示例如下。

如何合并几何体并保持每个几何体的颜色在R3F中。

英文:

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.

如何合并几何体并保持每个几何体的颜色在R3F中。

答案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 the vertexColors properties.

EXAMPLE

Let's say we want to merge 3 polygons with one color per polygone:

// Polygones to display
const zones = [{
  name:&#39;zone1&#39;,
  coords:[[-2,0],[-2,2],[-0.4,1], [-0.8,-1.5]],
  color: 0xff0000
},
{
  name:&#39;zone2&#39;,
  coords:[[-6,0],[-6,2],[-6.4,1], [-6.8,-1.5]],
  color: 0x0000ff
},
{
  name:&#39;zone3&#39;,
  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) =&gt; {
  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&lt;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 &lt; aColor.length; k+=3){
    aColor[k] = color.r;
    aColor[k+1] = color.g;
    aColor[k+2] = color.b;
  }
  geom.setAttribute(&#39;color&#39;, new THREE.BufferAttribute(aColor, 3));
  geometries.push(geom);
})
const newMerged = BufferGeometryUtils.mergeGeometries(geometries)
  • And in your jsx you would have the following:
&lt;mesh geometry={merged}&gt;
  {/* activate vertex color */}
  &lt;meshBasicMaterial vertexColors/&gt;
&lt;/mesh&gt;

An example of the implementation can be found here: Codesandbox

huangapple
  • 本文由 发表于 2023年5月31日 23:12:01
  • 转载请务必保留本文链接:https://go.coder-hub.com/76374983.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定