As the title states, I want to keep a light in position while rotating an object using OrbitControls. I currently have a box with a light shining on one side of it. I want to be able to rotate the box and have the light stay in position, lighting the other sides as I rotate the box. :) Here is my current code
`import React, { Suspense, useEffect, useState } from "react";
import { Canvas } from "@react-three/fiber";
import { OrbitControls, Preload, useGLTF } from "@react-three/drei";
import CanvasLoader from "../Loader";
const Island = ({ isMobile }) => {
const island = useGLTF("./block/scene.gltf");
return (
<mesh>
<hemisphereLight intensity={0.15} groundColor='black' />
{/* <spotLight
position={[0, -10, 10]}
angle={0.22}
penumbra={1}
intensity={2}
castShadow
shadow-mapSize={1024}
/> */}
<primitive
object={island.scene}
scale={isMobile ? 0.7 : 0.005}
position={isMobile ? [0, -4, -2.2] : [0, -4.2, 0]}
rotation={[0, 0, 0]}
/>
</mesh>
);
};
const IslandCanvas = () => {
const [isMobile, setIsMobile] = useState(false);
useEffect(() => {
// Add a listener for changes to the screen size
const mediaQuery = window.matchMedia("(max-width: 500px)");
// Set the initial value of the `isMobile` state variable
setIsMobile(mediaQuery.matches);
// Define a callback function to handle changes to the media query
const handleMediaQueryChange = (event) => {
setIsMobile(event.matches);
};
// Add the callback function as a listener for changes to the media query
mediaQuery.addEventListener("change", handleMediaQueryChange);
// Remove the listener when the component is unmounted
return () => {
mediaQuery.removeEventListener("change", handleMediaQueryChange);
};
}, []);
return (
<Canvas
frameloop='demand'
shadows
dpr={[1, 2]}
camera={{ position: [20, 3, 5], fov: 25 }}
gl={{ preserveDrawingBuffer: true }}
>
{/* <pointLight
intensity={1}
position={[0, -30, 1000]}
/> */}
<Suspense fallback={<CanvasLoader />}>
<group>
<pointLight
intensity={1}
position={[0, -30, 1000]}
/>
</group>
<group>
<OrbitControls
enableZoom={false}
maxPolarAngle={Math.PI / 2}
minPolarAngle={Math.PI / 2}
/>
<Island isMobile={isMobile} />
</group>
</Suspense>
<Preload all />
</Canvas>
);
};
export default IslandCanvas;`
I have tried wrapping the light in a separate group on the canvas, I have tried putting orbit controls inside of the object mesh and not the canvas, none of this has worked so far and I'm a little lost. This is my first overflow question I've posted so lmk if I'm leaving anything out
From what I have seen, there are two options here:
Attach the lights to the camera object, so that as the camera is moved around, the lights automatically follow the camera. For this to work, the camera must also be added to the scene.
import { Canvas } from '@react-three/fiber';
import { PointLight } from 'three';
const light = new PointLight();
light.position.set(1, 1, 0); // This position is relative to the camera's position
function Scene() {
return (
<Canvas
onCreated={({ camera, scene }) => {
camera.add(light);
scene.add(camera);
}}
>
{/* your scene */}
</Canvas>
);
}
Add lights to the scene, but update their position when OrbitControls update the camera position.
import { OrbitControls } from '@react-three/drei';
import { Canvas } from '@react-three/fiber';
import { useRef } from 'react';
import { PointLight } from 'three';
function Scene() {
const lightRef = useRef<PointLight>(null);
return (
<Canvas>
{/* your scene */}
<pointLight ref={lightRef} position={[1, 1, 0]} />
<OrbitControls
onChange={(e) => {
if (!e) return;
const camera = e.target.object;
if (lightRef.current) {
// This sets the point light to a location above your camera
// Note that this position is in world space, not relative to
// the camera
lightRef.current.position.set(0, 1, 0);
lightRef.current.position.add(camera.position);
}
}}
/>
</Canvas>
);
}