adjust model size

This commit is contained in:
DefectingCat
2023-05-16 14:23:41 +08:00
parent 20e358fb57
commit a349be156d
2 changed files with 61 additions and 20 deletions

View File

@ -1,11 +1,12 @@
'use client'; 'use client';
import { Canvas, useFrame, useLoader } from '@react-three/fiber'; import { useProgress } from '@react-three/drei';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'; import { Canvas, useFrame, useLoader, useThree } from '@react-three/fiber';
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader'; import { frameArea } from 'lib/utils';
import { Environment, OrbitControls, useProgress } from '@react-three/drei'; import { useRef } from 'react';
import { useRef, useState } from 'react';
import * as THREE from 'three'; import * as THREE from 'three';
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
const Model = () => { const Model = () => {
const mixer = useRef<THREE.AnimationMixer | null>(null); const mixer = useRef<THREE.AnimationMixer | null>(null);
@ -19,16 +20,27 @@ const Model = () => {
} }
); );
const [loading, setLoading] = useState(true); const camera = useThree((state) => state.camera);
useProgress((state) => { const process = useProgress((state) => {
if (state.progress >= 100) { if (state.progress < 100) return state.progress;
mixer.current = new THREE.AnimationMixer(gltf.scene);
gltf.animations.forEach((clip) => {
mixer.current?.clipAction(clip).play();
});
setLoading(false);
}
// After model loaded.
mixer.current = new THREE.AnimationMixer(gltf.scene);
gltf.animations.forEach((clip) => {
mixer.current?.clipAction(clip).play();
});
const box = new THREE.Box3().setFromObject(gltf.scene);
const boxSize = box.getSize(new THREE.Vector3()).length();
const boxCenter = box.getCenter(new THREE.Vector3());
frameArea(
boxSize * 0.8,
boxSize,
boxCenter,
camera as THREE.PerspectiveCamera
);
camera.position.z += 0.15;
camera.position.y -= 0.15;
return state.progress; return state.progress;
}); });
@ -46,13 +58,9 @@ const Model = () => {
const HomeModel = () => { const HomeModel = () => {
return ( return (
<Canvas> <Canvas>
<spotLight color={0xffffff} intensity={2} distance={100} angle={15} /> <spotLight color={0xffffff} intensity={1.5} distance={100} angle={15} />
<ambientLight color={0xffffff} intensity={1} /> <ambientLight color={0xffffff} intensity={0.5} />
<Model /> <Model />
{/*
<OrbitControls />
<Environment preset="sunset" background />
*/}
</Canvas> </Canvas>
); );
}; };

View File

@ -1,3 +1,5 @@
import * as THREE from 'three';
export const sortByDate = ( export const sortByDate = (
{ date: a }: { date: string }, { date: a }: { date: string },
{ date: b }: { date: string } { date: b }: { date: string }
@ -118,3 +120,34 @@ export const debounce: Debounce = (fn, ms) => {
}, ms); }, ms);
}; };
}; };
export const frameArea = (
sizeToFitOnScreen: number,
boxSize: number,
boxCenter: THREE.Vector3,
camera: THREE.PerspectiveCamera
) => {
const halfSizeToFitOnScreen = sizeToFitOnScreen * 0.5;
const halfFovY = THREE.MathUtils.degToRad(camera.fov * 0.5);
const distance = halfSizeToFitOnScreen / Math.tan(halfFovY);
// compute a unit vector that points in the direction the camera is now
// in the xz plane from the center of the box
const direction = new THREE.Vector3()
.subVectors(camera.position, boxCenter)
.multiply(new THREE.Vector3(1, 0, 1))
.normalize();
// move the camera to a position distance units way from the center
// in whatever direction the camera was from the center already
camera.position.copy(direction.multiplyScalar(distance).add(boxCenter));
// pick some near and far values for the frustum that
// will contain the box.
camera.near = boxSize / 100;
camera.far = boxSize * 100;
camera.updateProjectionMatrix();
// point the camera to look at the center of the box
camera.lookAt(boxCenter.x, boxCenter.y, boxCenter.z);
};