My r3f model cannot be scaled nor its position changed - reactjs

I'm trying to scale my model and change its position, but its not happening- I must be missing something. It's not webpack as the rest is updating fine and the model is loading. I used gltfjsx to create this file.
export default function Model({ ...props }) {
const group = useRef()
const { nodes } = useGLTF('./mymodel')
const material = useMemo(() => {
if (props.layer === DEFAULT_LAYER) return new THREE.MeshStandardMaterial({ color: new THREE.Color('rgba(62,53,105,1)'), roughness: 0.2, metalness: 0.9 })
else return new THREE.MeshBasicMaterial({ color: new THREE.Color('rgba(52,95,75,1)') })
}, [props.layer]);
return (
<group ref={group} dispose={null} position={[0,-500,0]} scale={[0.01, 0.01, 0.01]} {...props}>
<mesh geometry={nodes.Node.geometry} material={material}
layers={props.layer} receiveShadow castShadow />
</group>
)
}
export default function App() {
return (
<>
<Canvas camera={{ position: [0, 20, 12], fov: 35, near: 0.1, far: 2000 }} gl={{ antialias: true }} onCreated={state => state.gl.setClearColor( 0xffffff, 0)}>
<Suspense fallback={null}>
<Stage intensity={1}>
<Model layer = {DEFAULT_LAYER} />
</Stage>
</Suspense>
</Canvas>
<Loader />
</>
)
}
I have placed scale and position in the Model, mesh and group objects but none make a difference. How come? I can't change my camera position either.
My imports for Model.jsx:
import {useRef, useMemo} from 'react'
import { useGLTF } from '#react-three/drei'
import * as THREE from 'three'
My imports for App.jsx:
import React, { Suspense, useRef, useMemo } from 'react'
import { Canvas, useThree, useFrame } from '#react-three/fiber'
import { Loader, useFBO, Stage, Effects, Environment, OrbitControls } from '#react-three/drei'
import Model from './FortunaDraco'
import { FXAAShader } from 'three-stdlib'
import { AdditiveBlendingShader } from './shaders/AdditiveBlendingShader'
import { VolumetricLightShader } from './shaders/VolumetricLightShader'
import './App.css'

For anyone having this issue it was because of Stage

Related

OBJ Model not loading in react three fiber

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.

react-three-fiber 360 image darker than the original image

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

How to move camera with mouse move instead of mouse click

I was using react-three-fiber package and wanted to implement camera movement feature with mouse move instead of mouse click. For example, if you visit roundme.com then you will see a picture of a tour and when you move mouse camera, kinda, moves towards the position of pointer. So, to achieve it I decided to get current position of mouse and put that position to OrbitControls like this:
import React, { Suspense, useRef } from "react";
import { Canvas } from "react-three-fiber";
import { Html, OrbitControls } from "drei";
import "../../styles/index.css";
import { ReactReduxContext, Provider } from "react-redux";
import Portals from "../Portal/portal.component";
const Panorama = () => {
const mouse = useRef({ x: 0, y: 0 });
function getMousePos(e) {
console.log(e.clientX, e.clientY);
return { x: e.clientX, y: e.clientY };
}
return (
<>
<ReactReduxContext.Consumer>
{({ store }) => (
<Canvas
onMouseMove={(e) => (mouse.current = getMousePos(e))}
invalidateFrameloop
concurrent
camera={{ position: [50, 0, 0.1] }}
>
<OrbitControls
enableZoom={true}
enablePan={true}
dampingFactor={1}
minDistance={10}
maxDistance={500}
autoRotate
zoomSpeed={5}
autoRotateSpeed={0.5}
rotateSpeed={-1.4}
/>
<Suspense
fallback={
<Html center style={{ color: "white" }}>
loading...
</Html>
}
>
<Provider store={store}>
<Portals />
</Provider>
</Suspense>
</Canvas>
)}
</ReactReduxContext.Consumer>
</>
);
};
export default Panorama;
But camera does not move when I move mouse.
I'm not sure if you can use this same pattern with drei's OrbitControls, but here is how you can achieve it with the camera-controls package:
import CameraControls from 'camera-controls'
CameraControls.install({ THREE })
extend({ CameraControls })
function Controls() {
const ref = useRef()
const camera = useThree((state) => state.camera)
const gl = useThree((state) => state.gl)
useFrame((state, delta) => {
// update camera angles according to mouse position
ref.current.azimuthAngle = -state.mouse.x
ref.current.polarAngle = Math.PI / 2 + state.mouse.y
ref.current.update(delta)
})
return <cameraControls ref={ref} args={[camera, gl.domElement]} />
}
And then simply put <Controls /> inside of your <Canvas />.

React admin tree hierarchy and collapse buttons do not appear

I'm having a hard time trying to make ra-tree-ui-materialui work following this doc :
https://github.com/marmelab/react-admin/blob/master/packages/ra-tree-ui-materialui/README.md
I already have a react-admin backoffice with some fixture data, and I decided, after editing my App.js like explained in link above, to put my tree logic inside SegmentationList.js, which manages display of all Segmentations coming from an APIPlatform backend.
I commented datagrid logic already present in file, to test the tree alone. I kept all imports active and added those needed for the tree like in docs. With this code I manage to have the tree displayed, but with no hierarchy view at all, even when I set a row as child of another by editing, or when I do it via drag and drop.
When I try the latter, I actually view the child row nested inside its parent with collapse button for a few seconds only. Then it comes back to a flat tree.
I have tried to disable JSS in the file to see if style was guilty. I checked if react-dnd was installed and it is. I checked that parent field had value expected in child row by coming back to its edit page. Finally I went to backend side to check if parent field values in DB were consistent with what I saw in frontend, it was. Finally I had a look on this topic : https://github.com/marmelab/react-admin/issues/2980 since I also have the warning "Missing translation for key: "ra.tree.root_target"".
Thanks for your help.
First, here is my App.js file :
import React, {Component} from 'react';
import { Admin, Resource, mergeTranslations } from 'react-admin';
import { reducer as tree } from 'ra-tree-ui-materialui';
import englishMessage from 'ra-language-english';
import treeEnglishMessages from 'ra-tree-language-english';
import parseHydraDocumentation from '#api-platform/api-doc-parser/lib/hydra/parseHydraDocumentation';
import { hydraClient } from '#api-platform/admin';
import Locale from "./Resources/Locale/"
import Segmentation from "./Resources/Segmentation/"
import SegmentationTranslation from "./Resources/SegmentationTranslation/"
import Product from "./Resources/Product/"
import Attribute from "./Resources/Attribute/"
import ProductTranslation from "./Resources/ProductTranslation/"
import translations from './i18n';
import CustomRoute from './routes';
import themeReducer from './themeReducer';
import { Layout } from './layout';
import LocaleRetrieve from './Utils/LocaleRetrieve';
const messages = {
'en': mergeTranslations(englishMessage, treeEnglishMessages),
};
const dataProvider = api => hydraClient(api);
const httpEndpoint = process.env.REACT_APP_XXX_HTTP;
const apiDocumentationParser = httpEndpoint => parseHydraDocumentation(httpEndpoint)
.then(
({ api }) => ({api})
);
const i18nProvider = locale => {
// change of locale after initial call returns a promise
return translations[locale];
}
export default class extends Component {
state = { api: null };
componentDidMount() {
apiDocumentationParser(httpEndpoint).then(({ api }) => {
this.setState({ api });
}).catch((e) => {
console.log(e);
});
console.log(LocaleRetrieve());
};
render() {
if (null === this.state.api) return <div>Loading...</div>;
return (
<Admin api={ this.state.api }
apiDocumentationParser={ apiDocumentationParser }
dataProvider= { dataProvider(this.state.api) }
customReducers={{theme: themeReducer, tree}}
messages={translations}
locale="en"
i18nProvider={i18nProvider}
title="XXX"
customRoutes={CustomRoute}
appLayout={Layout}
>
<Resource name="locales" {...Locale} />
<Resource name="segmentations" {...Segmentation} />
<Resource name="segmentation_translations" {...SegmentationTranslation}/>
<Resource name="products" {...Product}/>
<Resource name="product_translations" {...ProductTranslation}/>
<Resource name="attributes" {...Attribute}/>
</Admin>
)
}
}
and here is my component with tree logic, located in src/Resources/Segmentation/SegmentationList.js :
import React, {Fragment} from 'react';
import {List, Datagrid, TextField, ChipField, BooleanField, ReferenceField, EditButton, ReferenceInput, AutocompleteInput, ShowButton, Filter, TextInput, Labeled, CardActions, ExportButton, RefreshButton, DeleteButton, SaveButton } from 'react-admin';
import LinkToTranslatations from './LinkToTranslations';
import AddChildButton from "./AddChildButton";
import ListChildButton from "./ListChildButton";
import PublishedButtons from './PublishedButtons';
import CreateSegmentationButtons from './CreateSegmentationButtons';
// for tree
import { withStyles } from '#material-ui/core/styles';
import { IgnoreFormProps, Tree, NodeForm, NodeActions, NodeView } from 'ra-tree-ui-materialui';
const styles = {
hash: {
marginLeft: '15px',
fontWeight: 'bold',
marginRight: '15px'
},
type: {
marginLeft: '15px',
marginRight: '15px',
textTransform: 'uppercase'
},
title: {
marginLeft: '15px',
marginRight: '15px'
}
};
// for tree
const SegmentationTreeActions = props => (
<NodeActions {...props}>
<LinkToTranslatations />
<ShowButton />
<IgnoreFormProps>
<EditButton />
<DeleteButton />
</IgnoreFormProps>
</NodeActions>
);
// tree
export const SegmentationList = withStyles(styles)(({ classes, ...props}) => (
<List {...props} perPage={10000}>
<Tree allowDropOnRoot enableDragAndDrop>
<NodeView actions={<SegmentationTreeActions />}>
<TextField source="hash" className={classes.hash} />
<TextField source="type" className={classes.type} />
<TextField source="title" className={classes.title} />
</NodeView>
</Tree>
</List>
));
export default SegmentationList;

How to use Konva Node with ReactJs

I want to use konva.js node nesting in react app. I need help on how to use it.
Thanks in advance.
I can advise you to use react-konva library
https://github.com/konvajs/react-konva
The examples with the draggable circles:
import React, { Component } from 'react';
import Konva from 'konva';
import { render } from 'react-dom';
import { Stage, Layer, Circle, Text } from 'react-konva';
class App extends Component {
handleDragStart = e => {
e.target.setAttrs({
scaleX: 1.3,
scaleY: 1.3
});
};
handleDragEnd = e => {
e.target.to({
duration: 0.5,
scaleX: 1,
scaleY: 1
});
};
render() {
return (
<Stage width={window.innerWidth} height={window.innerHeight}>
<Layer>
<Text text="You can drag a circle" />
{[...Array(10)].map(i => (
<Circle
key={i}
x={Math.random() * window.innerWidth}
y={Math.random() * window.innerHeight}
radius={20}
fill="green"
opacity={0.8}
draggable
onDragStart={this.handleDragStart}
onDragEnd={this.handleDragEnd}
/>
))}
</Layer>
</Stage>
);
}
}
render(<App />, document.getElementById('root'));
You need to add react, konva, react-dom and react-konva dependencies

Resources