How do convert vanilla js Three.EllipseCurve to react-three-fiber in more specified way

So basically in documentation of three.js the code of Ellipse Curve should be something like this…

const curve = new THREE.EllipseCurve(
	0,  0,            // ax, aY
	10, 10,           // xRadius, yRadius
	0,  2 * Math.PI,  // aStartAngle, aEndAngle
	false,            // aClockwise
	0                 // aRotation
);

const points = curve.getPoints( 50 );
const geometry = new THREE.BufferGeometry().setFromPoints( points );

const material = new THREE.LineBasicMaterial( { color: 0xff0000 } );

// Create the final object to add to the scene
const ellipse = new THREE.Line( geometry, material );

But I wanna know how to create in react-three-fiber… I have a sample code here but couldn’t imagine where the code should I put at.

// This is the extends
import { EllipseCurve } from 'three'

import { LineMaterial } from "three/examples/jsm/lines/LineMaterial"
import { LineGeometry } from "three/examples/jsm/lines/LineGeometry"
import { Line2 } from "three/examples/jsm/lines/Line2"

extend({ OrbitControls,EllipseCurve,LineMaterial,LineGeometry,Line2 });

...
// And this is how I will make ellipsecurve( circle in shape)
    const { size } = useThree()
    const [color, setColor] = useState("white")
    const ref = useRef()

    useEffect(() => {
        var curve = new THREE.EllipseCurve(0, 0, 45, 45, 0, 2 * Math.PI, false, 0)
        const points = curve.getSpacedPoints( 100 )
        
    },[])

    return(
        <line2>
            <lineGeometry attach="geometry" ref={ref}  />
            <lineMaterial attach="material" color={color} linewidth={5} resolution={[size.width, size.height]} />
        </line2>
   )

How do I put this here? I don’t understand hahahah… I don’t see any documentation in react-three-fiber about this…So I’m kinda lost…

it’s almost correct. for complex, imperative stuff you use it the same way you’d use it in vanilla (or find a good component abstraction that hides the boilerplate).

this could be a simple useMemo

const geometry = useMemo(() => {
  const curve = new THREE.EllipseCurve(0, 0, 10, 10, 0, 2 * Math.PI, false, 0)
  return new THREE.BufferGeometry().setFromPoints(curve.getPoints(50))
}, [])

return (
  <line2 geometry={geometry}>
    <lineMaterial color={color} linewidth={5} resolution={[size.width, size.height]} />
  </line2>
)

i am not 100% sure if this is how you use line2, i think it’s wrong. your vanilla example uses THREE.Line, but JSM/Line2 might be different. in the examples it doesn’t use plain buffergeometry but JSM/LineGeometry which has a setPoints method.

we also have abstractions in drei:

Line2: GitHub - pmndrs/drei: 🥉 useful helpers for react-three-fiber
QuadraticBezierLine: GitHub - pmndrs/drei: 🥉 useful helpers for react-three-fiber
CubicBezierLine: GitHub - pmndrs/drei: 🥉 useful helpers for react-three-fiber
CatmullRomLine: GitHub - pmndrs/drei: 🥉 useful helpers for react-three-fiber

you can look into these to study how line2 is being used, or if you want to create an abstraction around ellipsecurve, it will make it more re-usable (and at this point consider adding it to drei as well pls)

ps, small example using QuadraticBezierLine

1 Like

Sir I tried it but why the ellipsecurve line doesn’t show in the scene??
It doesn’t have error but I can’t see it.

as i said, i don’t think threes line2 works the way you use it. your vanilla example uses new THREE.Line( geometry, material )

1 Like

hahaha sorry about that…so where should I follow it? in your pmndrs/drei ?

if you want a thin like like in your vanilla example everything’s fine except <line2>, again you’re using line2 wrong, you need to consult the documentation or find threejs examples that use it correctly. though if you just want a thick line with a ellipse-curve, just throw the curve points into drei/Line, that would be the easiest. that component is documented in drei.

Sorry but I have another question if this is right? I can’t find the more documentation in drei/line but do you mean something like this?

...
import { Line } from '@react-three/drei'
...
    const geometry = useMemo(() => {
        const curve = new THREE.EllipseCurve(0, 0, 50, 50, 0, 2 * Math.PI, false, 0)
        return new THREE.BufferGeometry().setFromPoints(curve.getPoints(50))
    }, [])
...
        <Line
            color={color}
            linewidth={5}
            geometry={geometry}
        />

but this code doesn’t works…

Sorry but I had to do it…I can’t really understand sometimes the documentation if its not info for me to clarify in my head.

I just happen to have a Drei Line from THREE.EllipseCurve demo.

3 Likes

I see thanks a lot…I just want to redo again my code before in vanilla and I don’t know how to convert it into r3f thanks.

nice, i was wondering why just giving it the result of getPoints didn’t work and turns out curve.getPoints returns Vector2. mapping it to V3 removes the extra step with the buffergeometry.

  const points = useMemo(() => {
    return new THREE.EllipseCurve(0, 0, 3, 1.5, 0, 2 * Math.PI, false, 0)
      .getPoints(100)
      .map((p) => new THREE.Vector3(p.x, p.y, 0))
  }, [])
2 Likes

made a small update, now line takes Vector3[], Vector2[], [x, y, z][] and [x, y][]

const points = useMemo(() =>
  new THREE.EllipseCurve(0, 0, 3, 1.5, 0, 2 * Math.PI, false, 0).getPoints(100)
, [])
return <Line points={points} color="turquoise" lineWidth={20} />

@Myth_Xenodo even your original code above, which wouldn’t work with three/jsm/lines/line2, would most likely start to run after the update.

2 Likes