The glb model is getting render twice and i have no clue why, has anyone been here?
This is model
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
export function loadGLTFModel(
scene,
glbPath,
options = { receiveShadow: true, castShadow: true }
) {
const { receiveShadow, castShadow } = options;
return new Promise((resolve, reject) => {
const loader = new GLTFLoader();
loader.load(
glbPath,
(gltf) => {
const obj = gltf.scene;
obj.name = "dog";
obj.position.y = 0;
obj.position.x = 0;
obj.receiveShadow = receiveShadow;
obj.castShadow = castShadow;
scene.add(obj);
obj.traverse(function (child) {
if (child.isMesh) {
child.castShadow = castShadow;
child.receiveShadow = receiveShadow;
}
});
resolve(obj);
},
undefined,
function (error) {
reject(error);
}
);
});
}
This is the component
import { useState, useEffect, useRef, useCallback } from "react";
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import { loadGLTFModel } from "./model";
function easeOutCirc(x) {
return Math.sqrt(1 - Math.pow(x - 1, 4));
}
const VoxelDog = () => {
const refContainer = useRef();
const [loading, setLoading] = useState(true);
const [renderer, setRenderer] = useState();
const [_camera, setCamera] = useState();
const [target] = useState(new THREE.Vector3(-0.5, 1.2, 0));
const [initialCameraPosition] = useState(
new THREE.Vector3(
20 * Math.sin(0.2 * Math.PI),
10,
20 * Math.cos(0.2 * Math.PI)
)
);
const [scene] = useState(new THREE.Scene());
const [_controls, setControls] = useState();
const handleWindowResize = useCallback(() => {
const { current: container } = refContainer;
if (container && renderer) {
const scW = container.clientWidth;
const scH = container.clientHeight;
renderer.setSize(scW, scH);
}
}, [renderer]);
/* eslint-disable react-hooks/exhaustive-deps */
useEffect(() => {
const { current: container } = refContainer;
if (container && !renderer) {
const scW = container.clientWidth;
const scH = container.clientHeight;
const renderer = new THREE.WebGLRenderer({
antialias: true,
alpha: true,
});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(scW, scH);
renderer.outputEncoding = THREE.sRGBEncoding;
container.appendChild(renderer.domElement);
setRenderer(renderer);
// 640 -> 240
// 8 -> 6
const scale = scH * 0.001 + 4.8;
const camera = new THREE.OrthographicCamera(
-scale,
scale,
scale,
-scale,
0.01,
50000
);
camera.position.copy(initialCameraPosition);
camera.lookAt(target);
setCamera(camera);
const ambientLight = new THREE.AmbientLight(0xcccccc, 1);
scene.add(ambientLight);
const controls = new OrbitControls(camera, renderer.domElement);
controls.autoRotate = true;
controls.target = target;
setControls(controls);
loadGLTFModel(scene, "/dog.glb", {
receiveShadow: false,
castShadow: false,
}).then(() => {
animate();
setLoading(false);
});
let req = null;
let frame = 0;
const animate = () => {
req = requestAnimationFrame(animate);
frame = frame <= 100 ? frame + 1 : frame;
if (frame <= 100) {
const p = initialCameraPosition;
const rotSpeed = -easeOutCirc(frame / 120) * Math.PI * 20;
camera.position.y = 20;
camera.position.x =
p.x * Math.cos(rotSpeed) + p.z * Math.sin(rotSpeed);
camera.position.z =
p.z * Math.cos(rotSpeed) - p.x * Math.sin(rotSpeed);
camera.lookAt(target);
} else {
controls.update();
}
renderer.render(scene, camera);
};
return () => {
console.log("unmount");
cancelAnimationFrame(req);
renderer.dispose();
};
}
}, []);
useEffect(() => {
window.addEventListener("resize", handleWindowResize, false);
return () => {
window.removeEventListener("resize", handleWindowResize, false);
};
}, [renderer, handleWindowResize]);
return (
<div
style={{ height: "400px", width: "540px", position: "" }}
ref={refContainer}
>
{loading && (
<span style={{ position: "absolute", left: "50%", top: "50%" }}>
Loading...
</span>
)}
</div>
);
};
export default VoxelDog;
and here i declare it just once!
<Box
as="main"
style={{}}
pb={8}
className="d-flex justify-content-center"
>
<Container style={{}} maxW="container.md" pt={14}>
<VoxelDog />
</Container>
</Box>
Any idea? thanks so much!