I'm new to react-three-fiber, so I really think my problem is easy but I almost give up on it 😅.
the problem :
I have a 3D model it renders ok but it’s away too big
I have to zoom out to 25% just to see almost half the model (see the picture)
what I wanted:
the model to be way smaller so I can put it as a small background for my website.
Here’s the full model
I want to put the model.js but it’s too many lines 😅, there’s nothing special really I use the gltfjsx command line to transfer my .gltf file to .js file and I didn’t do any changes to it.
and here's my app.js
import React, { Suspense } from "react";
import { Canvas } from "#react-three/fiber";
import { OrbitControls } from "#react-three/drei";
import './App.css';
import Model from './components/Bedroom';
function App() {
return (
<Canvas>
<OrbitControls />
<ambientLight intensity={0.6} />
<directionalLight intensity={0.5} />
<Suspense fallback={null}>
<Model/>
</Suspense>
</Canvas>
);
}
export default App;
use Stage from 'three/drei' to stage your model it will fix this issue,
example:
<Canvas>
<Stage preset="rembrandt" intensity={1} environment="city">
<Model/>
...
<Stage/>
<Canvas/>
Or:
control your zoom inside camera of canvas like this
<Canvas camera={{ fov: 35, zoom: 1.3, near: 1, far: 1000 }}>
...
<Canvas/>
Myabe you are just trying to scale your model, in that case you just need to add scale={[sclaefactorx,scalefactory,sclaefactorz]} on your model like so :
import { Canvas } from "#react-three/fiber";
import { OrbitControls } from "#react-three/drei";
import './App.css';
import Model from './components/Bedroom';
function App() {
return (
<Canvas>
<OrbitControls />
<ambientLight intensity={0.6} />
<directionalLight intensity={0.5} />
<Suspense fallback={null}>
<Model scale={[0.1,0.1,0.1]}/>
</Suspense>
</Canvas>
);
}
export default App;
Since in the model file created from gltfjsx there should be a {...props} on the created group the scale will be applied directly to the mesh group
Related
I'm trying to add an OBJ Model (armchair.obj) but it's not being loaded. I'm using React three fiber library.
Here's my codesandbox: CodeSandbox
There's no problem with the model because I tried to load it using some other website and it is being loaded.
Anyway, I tried uploading another model (spongebob.obj) but it's not being really visible
However, in the other website, it's visible:
So, here's my codesandbox link
But, if you prefer the code here:
My App.js component:
import React, { Suspense } from "react";
import { Canvas } from "#react-three/fiber";
import { OrbitControls } from "#react-three/drei";
import LoadModel from "./components/LoadModel";
import Loader from "./components/Loader";
const App = () => {
return (
<main className="main-area">
<div id="canvas-container">
<Canvas pixelratio={[1, 2]} camera={{ position: [15, 15, 15], fov: 50, scale: [2,2,2] }}>
<ambientLight intensity={1} />
<Suspense fallback={<Loader />}>
<LoadModel url="./spongebob.obj" />
</Suspense>
<OrbitControls />
</Canvas>
</div>
</main>
);
};
export default App;
My LoadModel.js component:
import React, { useMemo, useState } from "react";
import { OBJLoader } from "three/examples/jsm/loaders/OBJLoader";
const LoadModel = ({ url }) => {
const [obj, set] = useState();
// useMemo(() => new OBJLoader().load(url, set), [url])
useMemo(() => new OBJLoader().load(url, set), [url]);
//useMemo(() => new GLTFLoader().load(url, set), [url])
return obj ? <primitive object={obj} dispose={null} /> : null;
};
export default LoadModel;
You can improve the rendering of the SpongeBob model by adding a directional light to your scene. A single ambient light is not sufficient for proper illumination. Try adding the following line to your codesandbox:
<directionalLight />
The chair model has unfortunately some design issues. It has an extreme scale and is highly translated. I suggest you scale the model down and then center it after the loading process. However, it would be better to fix the model in a DCC tool like Blender and model the chair according to real world units.
I'm currently having an issue with AWS. I have a simple react-three-fiber build, that renders a car model from a .gltf file. The model and build run fine locally but not on AWS. The error I get is
Could not load /tesla_model_3/scene.gltf: Unexpected token < in JSON at position 0
I can't figure out why AWS won't load the JSON object of the model and instead is passing in an HTML. here is the site deployed: https://master.d258lkzp17ij6b.amplifyapp.com/
It could be a pathing issue, but it runs fine on a local server.
the file scene.gltf is the /public folder
and here are the code blocks for the model and the call to the component.
also here is the Github for the files if needed: https://github.com/SBrandon0432/tesla-car-shop/tree/Master/src
import React, {lazy, Suspense} from 'react';
import { useLoader } from '#react-three/fiber';
import * as THREE from 'three';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'
const Model = props =>{
const model = useLoader(
GLTFLoader, props.path
)
return (
<Suspense>
<primitive object={model.scene} scale={'.50'} position={[0,0,0]}/>
</Suspense>
)
}
export default Model
import React, {useRef, useEffect, Suspense, lazy} from "react";
import { ReactThreeFiber, Canvas, useFrame, extend, useThree, useLoader } from 'react-three-fiber';
import * as THREE from 'three';
import Box from './Box';
import Background from "./Background";
import Bulb from "./Bulb";
import Controls from "./Controls";
import Floor from "./Floor";
const Model = lazy(() => import("./Model"));
const ThreeD = () => {
return (
<Canvas className="ThreeD"
shadows
camera={{position:[200,200,200]}}
>
<ambientLight intensity={1.5}/>
<Bulb position={[0, 3, 0]}/>
<Suspense fallback={null}>
<Model
path={'/tesla_model_3/scene.gltf'}
/>
</Suspense>
<Controls/>
<axesHelper args={[5]}/>
<Suspense fallback={null}>
<Box position={[4,2,0]}/>
</Suspense>
<Suspense fallback={null}>
<Background/>
</Suspense>
<Floor position={[0,-.5,0]}/>
</Canvas>
)
}
export default ThreeD;
I'm drawing a 3d model with the following configuration.
react-three-fiber
#react-three/drei
The following is a CodeSandBox with a model drawn.
CodeSandBox-A
The drawn model is close to the top of the canvas, and I want to center it.
Could you please tell me how to center the model on the canvas?
This is the first time I've touched Three.js, so I'm sure I may have made some elementary mistakes.
The code is as follows.
I referred to the following document for the props of the Canvas component.
React Three Fiber Documentation
import { useMemo, Suspense } from "react";
import "./style.css";
import { Canvas } from "#react-three/fiber";
const { useGLTF, OrbitControls, Stage } = require("#react-three/drei");
const CanvasContainer = () => {
const { scene } = useGLTF("/scene.glb");
return (
<Canvas camera={{ fov: 70, position: [0, 1000, 1000] }}>
// No matter what I put in this "position" value, I could not see any change in the canvas.
<OrbitControls enablePan={true} enableZoom={true} enableRotate={true} />
<Stage>
<group dispose={null}>
<primitive scale={[1, 1, 1]} object={scene} />
</group>
</Stage>
</Canvas>
);
};
const App = () => {
const isWindow = typeof window === "undefined";
const memoCanvas = useMemo(() => <CanvasContainer />, []);
return (
<>
<h1>Canvas</h1>
<div className="canvas_container">
{!isWindow && <Suspense fallback={<div />}>{memoCanvas}</Suspense>}
</div>
</>
);
};
export default App;
setDefaultCamera removed in v6.x. · Issue #1147 · pmndrs/react-three-fiber
I also tried the code to use useThree as described in the above Issue.
The following is its CodeSandBox.
CodeSandBox-B
As you can see from the CodeSandBox, I was unable to move the camera.
give orbitcontrols the "makeDefault" prop, then it should in the center. otherwise check out dreis Bounds component. see: https://twitter.com/0xca0a/status/1453807293074661385
the memocanvas thing btw makes no sense, don't put jsx into usememo.
I'm trying to create a 360 image using react-three-fiber. The 360 viewer is working perfectly as it purposed but the generated image is darker than the original image.
Here's the screenshot from my 360 viewer
Here's the original image
Here's my code
import React, { Suspense } from "react";
import { useTexture, OrbitControls } from "#react-three/drei";
import { Canvas } from "#react-three/fiber";
import * as THREE from "three";
const Generate360Image = (props) => {
var myTexture = useTexture(props.imageLocation);
return (
<>
<mesh
position={[0, 0, 0]}
>
<sphereGeometry attach="geometry" args={[500, 60, 60]} />
<meshBasicMaterial
attach="material"
map={myTexture}
side={THREE.DoubleSide}
/>
</mesh>
</>
);
};
class GenerateImage extends React.Component {
render() {
return (
<Canvas style={{ width: "100%", height: "100%" }}>
<Suspense fallback={null}>
<Generate360Image
imageLocation={this.props.myImage}
className="image-canvas"
/>
</Suspense>
<OrbitControls
autoRotate="true"
autoRotateSpeed={0.4}
minDistance={5}
maxDistance={80}
/>
</Canvas>
);
}
}
export default GenerateImage;
Any help will be appreciated. Thanks!
try use meshPhysicalMaterial instead of meshBasicMaterial. meshBasicMaterial does not properly reflect lightings.
compare these two samples from three.js docs
meshBasicMaterial
meshPhysicalMaterial
My App.jsx
import "./App.css";
import { Canvas } from "#react-three/fiber";
import React, { Suspense } from "react";
import { Html, useProgress } from "#react-three/drei";
const Scene = React.lazy(() => import('./components/Scene.jsx'));
function Loader() {
const { progress } = useProgress();
return <Html center>{progress} % loaded</Html>
}
function App() {
return (
<div id="canvas">
<Canvas>
<Suspense fallback={<Loader />}>
<Scene />
</Suspense>
</Canvas>
</div>
);
}
export default App;
My Scene.jsx
function Scene() {
<>
<ambientLight intensity={0.2} />
<directionalLight />
<GizmoHelper
alignment="bottom-right"
margin={[80, 80]}
>
<GizmoViewport
axisColors={["red", "green", "blue"]}
labelColor="black"
/>
</GizmoHelper>
<Text
position={[-3, 0, 0]}
anchorX="center"
anchorY="middle"
fontSize="1.5"
outLineBlur="5"
outlineColor="red"
curveRadius="2.9"
font="db.onlinewebfonts.com/t/02654c5f87934978cd2129477ad40869.ttf">
Hello world
<meshStandardMaterial
color="#ec2d2d"
opacity="1"
roughness="0"
metalness="0.3"
normalMap={normalMap}
/>
</Text>
<OrbitControls />
<Environment preset="city" background="true" />
</>
);
}
My problem:
Every time I start the app the environment doesn't load and I get the following error:
Warning: Cannot update a component (`Loader`) while rendering a different component (`Environment`)
If I change the preset while the live server is running the environment updates and shows instantly.
I have already tried to write a function and render the environment only when the window is loaded but I still got the same error.
I have read somewhere I could use a setTimeout but not sure whether this the right approach.
If anyone could point me in the right direction.
Update:
I did not include the fact that I was using the GizmoHelper component.
Removing the GizmoHelper from the scene solved the problem.
I have added the GizmoHelper in above code in case someone else has the same problem.
Further Update:
I noticed the error is still logged in the console but now it does not affect the initial rendering of the environment anymore.
Might still cause an issue further down the road though.