I’m trying to embed a Sketchfab 3D model in my React JSX hero section, but every time I do, the model appears extremely small—like a single pixel. However, the model remains tiny. How can I properly size and scale the 3D model inside my hero section so it fits well and is fully visible? Traveler - Download Free 3D model by maxpanysh [f86f5f2] - Sketchfab
im trying to use that exact model directed by the link. Other models appear fine but not this.
Any help is appreciated!
import React, { Suspense } from “react”;
import { Canvas } from ‘@react-three/fiber’;
import { useGLTF, Environment, OrbitControls, Html } from ‘@react-three/drei’;
import “./HeroModel3D.css”;
// Simplified model component using useGLTF
function PiggyModel(props) {
const { scene } = useGLTF(‘/piggymodel/Pbr/traveler.glb’);
return <primitive object={scene} {…props} />;
}
// Loader component for displaying during model loading
function Loader() {
return (
I used this code to load Sketchfab models, which allows you to supply a bounding box and the model will be loaded into that box. This creates a hidden input element and auto-clicks it, but you can do it other ways if you already have such an element. (I’m not using React, and this is triggered by some other action)
let loadGLBModel = function(bounds = { min: { x: -5, y: 0, z: -5 }, max: { x: 5, y: 5, z: 5 } }) {
// Create a file input element
const fileInput = document.createElement('input');
fileInput.type = 'file';
fileInput.accept = '.glb';
fileInput.style.display = 'none';
document.body.appendChild(fileInput);
// Trigger file selection dialog
fileInput.click();
// Handle file selection
fileInput.addEventListener('change', function(event) {
const file = event.target.files[0];
if (!file) {
document.body.removeChild(fileInput);
return;
}
const fileURL = URL.createObjectURL(file);
gltfLoader.load(fileURL, function(gltf) {
// Remove previous model if it exists
if (currentModel) {
scene.remove(currentModel);
}
const model = gltf.scene;
currentModel = model;
// Calculate model dimensions
const boundingBox = new THREE.Box3().setFromObject(model);
const size = new THREE.Vector3();
boundingBox.getSize(size);
// Calculate target dimensions
const targetSize = {
x: bounds.max.x - bounds.min.x,
y: bounds.max.y - bounds.min.y,
z: bounds.max.z - bounds.min.z
};
// Calculate scale factor preserving aspect ratio
const scaleX = targetSize.x / size.x;
const scaleY = targetSize.y / size.y;
const scaleZ = targetSize.z / size.z;
const scale = Math.min(scaleX, scaleY, scaleZ);
// Apply uniform scaling
model.scale.set(scale, scale, scale);
// Re-calculate bounding box after scaling
const scaledBox = new THREE.Box3().setFromObject(model);
const center = new THREE.Vector3();
scaledBox.getCenter(center);
const targetCenter = new THREE.Vector3(
(bounds.min.x + bounds.max.x) / 2,
bounds.min.y, // Use minimum Y to place on ground
(bounds.min.z + bounds.max.z) / 2
);
// Calculate the offset differently for Y to align bottom of model with ground
model.position.x = targetCenter.x - center.x;
model.position.y = targetCenter.y - (scaledBox.min.y - model.position.y); // Align bottom with ground
model.position.z = targetCenter.z - center.z;
// Add to scene and start animation loop if not already running
scene.add(model);
if (!animationLoopRunning) {
animationLoopRunning = true;
renderer.setAnimationLoop(animate);
}
console.log(`Model "${file.name}" loaded and scaled to fit bounds`);
// Clean up
URL.revokeObjectURL(fileURL);
document.body.removeChild(fileInput);
}, function(xhr) {
// Progress callback
console.log(`${(xhr.loaded / xhr.total * 100).toFixed(2)}% loaded`);
}, function(error) {
// Error callback
console.error('Error loading model:', error);
URL.revokeObjectURL(fileURL);
document.body.removeChild(fileInput);
});
});
// Clean up if dialog is closed without selection
fileInput.addEventListener('cancel', function() {
document.body.removeChild(fileInput);
});
};
Try wrap model in that BB for skinnedmesh propsed by @donmccurdy
const vector = new THREE.Vector3();
const box = new THREE.Box3().makeEmpty();
const position = mesh.geometry.attributes.position;
for ( let i = 0, il = position.count; i < il; i ++ ) {
vector.fromBufferAttribute( position, i );
mesh.boneTransform( i, vector );
mesh.localToWorld( vector );
box.expandByPoint( vector );
}
And secondly, keep in mind that model [maybe] was exported from software with incorrect scale settings. Try import that model to Three.js editor, then will appear exact the same, small size.