How to Attach Tight Rigid Body Physics to Extruded SVG with React Three Rapier

61 Views Asked by At

I've also asked this on Three.js Discourse.

I'm trying to get to a tight inferred mesh from @react-three/rapier's <RigidBody> on an extruded SVG geometry, much like the hull example in this CodeSandbox from their docs. However, so far, the best inferred shape I've got is a cuboid, and it also outpositions the collider.

When I try to apply a hull on it, here's the error I get:

Unhandled Runtime Error
TypeError: Cannot read properties of undefined (reading 'array')

Since this is a mesh of meshes, I think it gets lost? I don't know. Maybe I need something like an <InstancedMesh>? I have no idea. Sorry, I'm new to this physics thing.

Anyways, here's a CodeSandbox based on that other one with the extruded SVG.

And, for reference, here's the extruded SVG code:

import { useMemo } from "react";

import * as THREE from "three";
import { SVGLoader } from "three/examples/jsm/Addons.js";
import { useLoader } from "@react-three/fiber";

type ExtrudedSvgProps = {
  filename: string;
  scale?: number;
  position?: [number, number, number];
};
export default function ExtrudedSvg({
  filename,
  scale = 1,
  position = [-10, 10, 0],
}: ExtrudedSvgProps) {
  const svgData = useLoader(SVGLoader, filename);
  const shapes = useMemo(() => {
    return svgData.paths.map((p) => p.toShapes(true));
  }, [svgData]);

  return (
    <mesh
      scale={scale}
      rotation={[Math.PI, 0, 0]}
      position={[position[0] + 5, position[1] - 2, position[2] + 2]}
    >
      {shapes.map((s, i) => (
        <mesh key={i} position={[0, 0, 0]}>
          <extrudeGeometry
            args={[
              s,
              {
                depth: 5,
                bevelEnabled: false,
                steps: 30,
              },
            ]}
          />
          <meshPhongMaterial
            attach="material"
            color={svgData.paths[i].color}
            side={THREE.DoubleSide}
          />
        </mesh>
      ))}
    </mesh>
  );
}

And here's how I'm using it:

<RigidBody colliders="cuboid" position={[-5, 20, 0]}>
  <ExtrudedSvg
    filename="fanaro.io.svg"
    scale={0.1}
    position={[-5, 10, 0]}
  />
</RigidBody>
1

There are 1 best solutions below

0
psygo On

Instead of using a set of <mesh>es inside a <mesh>, if you put them inside a fragment (<></>) or a <group>, it works:

<group>
  {shapes.map((s, i) => (
    <mesh ...>
      ...
    </mesh>
  ))}
</group>