I am new to the library and I would like to do something that i think is simple to have a sphere of diameter the same as the canvas.
I thought what I was doing was simple, but I was mistaken, I tried reading the documentation for answers but I have not found much, I tried AIs but to no avail…
I tried to calculare the readius based on the z distance but the diameter of the sphere is not the width…
Can someone help ??
This is the code
import { useRef, useEffect, useState, useCallback } from "react";
import { Canvas, useThree } from "@react-three/fiber";
import * as THREE from "three";
function ResizableSphere() {
const sphereRef = useRef<THREE.Mesh>(null);
const { size, camera } = useThree();
const [radius, setRadius] = useState(1);
const { getCurrentViewport } = useThree((state) => state.viewport);
const { width, height, factor } = getCurrentViewport(camera, [0, 0, 1]);
const resizeHandler = useCallback(() => {
if (sphereRef.current) {
console.log(width, height, factor);
const canvasWidth = width * factor;
const aspect = width / height;
const distance = camera.position.z / 2;
console.log("distance", distance);
const vFOV = THREE.MathUtils.degToRad(
(camera as THREE.PerspectiveCamera).fov
);
console.log(distance, vFOV, aspect);
const height_ = 2 * Math.tan(vFOV / 2) * distance;
const width_ = height_ * aspect;
const newRadius = width_ / 2;
console.log(
`Canvas Width: ${canvasWidth}, Calculated Width: ${width}, New Radius: ${newRadius}`
);
setRadius(newRadius);
}
}, [size, camera, width, height, factor]);
useEffect(() => {
resizeHandler();
window.addEventListener("resize", resizeHandler);
return () => {
window.removeEventListener("resize", resizeHandler);
};
}, [resizeHandler]);
useEffect(() => {
if (sphereRef.current) {
const newGeometry = new THREE.SphereGeometry(radius, 32, 32);
if (sphereRef.current.geometry)
sphereRef.current.geometry.dispose();
sphereRef.current.geometry = newGeometry;
}
}, [radius]);
return (
<mesh ref={sphereRef} scale={[1, 1, 1]}>
<meshStandardMaterial color="orange" />
</mesh>
);
}
function MyCanvas() {
return (
<Canvas camera={{ position: [0, 0, 10] }}>
<ambientLight intensity={0.5} />
<pointLight position={[0, 0, 10]} />
<ResizableSphere />
</Canvas>
);
}
export default MyCanvas;
Lorenzo Gilardi is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.