pmndrs / drei

🥉 useful helpers for react-three-fiber
https://docs.pmnd.rs/drei
MIT License
8.41k stars 707 forks source link

Multiple materials with RoundedBox #180

Closed Sharlaan closed 4 years ago

Sharlaan commented 4 years ago

Hello and amazing job with this lib drei !

I want to display a Dice with colored faces (and another with dotted faces), so multiple materials.

I discovered your nice RoundedBox component and tried to apply an array of materials but does not work :

import React, { useRef, useState } from 'react';
import { useFrame } from "react-three-fiber";
import { RoundedBox } from '@react-three/drei';

export default function Dice(props) {
  const [active, setActive] = useState(false);

  const mesh = useRef();
  // Rotate mesh every frame, this is outside of React without overhead
  useFrame(() => {
    if (mesh?.current) {
      mesh.current.rotation.x = mesh.current.rotation.y += 0.01;
    }
  });

  const materials = ['red', 'green', 'blue', 'cyan', 'magenta', 'yellow'].map((color) => (
    <meshBasicMaterial attachArray="material" color={color} />
  ));

  return (
    <RoundedBox
      {...props}
      ref={mesh}
      rotation={[Math.PI / 2, 0, 0]}
      scale={active ? [1.5, 1.5, 1.5] : [1, 1, 1]}
      args={[1, 1, 1]} // Width, Height and Depth of the box
      radius={0.1} // Border-Radius of the box
      smoothness={4} // Optional, number of subdivisions
      onClick={(e) => setActive(!active)}
    >
       {materials}
    </RoundedBox>
  );

  // working code but non-rounded box :/
  // return (
  //   <mesh
  //     {...props}
  //     ref={mesh}
  //     rotation={[Math.PI / 2, 0, 0]}
  //     scale={active ? [1.5, 1.5, 1.5] : [1, 1, 1]}
  //     onClick={(e) => setActive(!active)}
  //   >
  //     <boxBufferGeometry attach="geometry" args={[1, 1, 1]} />
  //     {materials}
  //   </mesh>
  // );
}

i'm getting this : image

looks like my array of materials is not reaching the boxBufferGeometry inside the RoundeBox ?

What can i do to apply my materials ?

gsimone commented 4 years ago

This goes a little bit over my knowledge of three, but material arrays are handled using geometry groups, which have to be created when constructing the geometry:

https://github.com/mrdoob/three.js/blob/master/src/geometries/BoxBufferGeometry.js try searching in the code for "group" and you'll see what I'm talking about.

I don't think rounded box, with our implementation, can support this, since we don't know the number of vertices before creating the geometry, since it's created via extrusion.

The soon-to-be-released official version of this geometry ( https://github.com/mrdoob/three.js/blob/45b0103e4dd9904b341d05ed991113f2f9edcc70/examples/jsm/geometries/RoundedBoxBufferGeometry.js ) also doesn't seem to support multi material, so you may be out of luck

Sharlaan commented 4 years ago

Ok thanks, guess i'll stick to boxGeom :/

theCocoonStudio commented 3 years ago

@gsimone Can I reimplement this component?

gsimone commented 3 years ago

Sure!