Why lookAt is not working in react-three-fiber mesh?

How does lookAt in react-three/fiber works on passing mesh? I don’t understand…so basically I have a field of boxes with 10 margins…but I want all box lookAt the center of surface but it doesn’t work…Here is the code…

This is the surface

function City(props) {
    return (
        <object3D>
            <mesh
            // ref={ref}
            {...props}
            scale={[100,100,0.1]}
            rotation = {[Math.PI/2,0,0]}
            >
                <boxGeometry args={[1,1,1]}></boxGeometry>
                <meshStandardMaterial 
                    color={"#232323"} 
                    roughness="0.5" 
                    metalness="0.3" 
                    emissive={"#000000"} 
                ></meshStandardMaterial>
            </mesh>
            {Array.from({length:9},(_,i) => {
                return (Array.from({length:9},(_,ix) => {
                    if (i > 1 && i < 7 && ix > 1 && ix <7) {

                    } else {
                        return (
                            <City2 
                                lookAt={[(i - 4)*10,props.position[1] + 0.5,(ix - 4)*10]} 
                                delay={i + ix} 
                                position={[(i - 4)*10,props.position[1] + 0.5,(ix - 4)*10]}
                            ></City2>
                        )
                    }
                }))
            })}
        </object3D>
    )
}

And this is the blocks

function City2({position,delay,lookAt}) {
    
    const ref = useRef()
    useEffect(() => {
        function gsapIncrease(args,x,y,z) {
            gsap.fromTo(args,{
                y:1
            },{
                y:y,
                delay:delay / (Math.sqrt(delay)),
                duration:2,
                ease:"ease.inOut"
            })
        }
        gsapIncrease(ref.current.scale,0,10,0)
        gsapIncrease(ref.current.position,0,5,0)
    },[])

And this is the part of lookAt City 2

    return(
        <mesh
            position={[position[0],0,position[2]]}
            lookAt = {[0,0,0]}
            scale={[4,5,2]}
            ref={ref}
        >
            <boxGeometry  args={[1,1,1]}></boxGeometry>
            <meshStandardMaterial
                color={"#232323"} 
                roughness="0.5" 
                metalness="0.3" 
                emissive={"#000000"} 
            ></meshStandardMaterial>
        </mesh>
    )
}

lookAt is a function. what you are doing there is this:

const mesh = new THREE.Mesh()
mesh.lookAt = [0, 0, 0]

and that’s just not how threejs works. fiber is not wrapping three, or altering three, it is threejs. if you open the docs and see a function, don’t expect fiber to magically make it something else bc it seems more convenient.

https://threejs.org/docs/index.html?q=ob#api/en/core/Object3D.lookAt

since threejs will always be a mixture between declarativity and imperative actions react gives you means to control the later, technically lookAt is a side effect:

const ref = useRef()
useLayoutEffect(() => {
  ref.current.lookAt(dir)
}, [dir])
return <mesh ref={ref} />

you can also do this, i would prefer uLE

<mesh onUpdate={self => self.lookAt(dir)} />
2 Likes

ps

in react jsx can self close if it doesn’t contain children, makes for cleaner code

<boxGeometery />
1 Like