I have tried using react-three-fiber and react-drei to make a model but the target of the OrbitControl is making it appear to high
import React, { useRef, useState, Suspense, useEffect } from 'react'
import { Canvas, useFrame, useLoader, useThree} from '#react-three/fiber'
import { ContactShadows, Environment, useGLTF, OrbitControls, PerspectiveCamera } from "#react-three/drei"
import { proxy, useSnapshot } from 'valtio'
import {HexColorPicker} from "react-colorful"
...
export default function App() {
return (
<>
<Picker/>
<Canvas camera>
<PerspectiveCamera makeDefault position={[0.1, 0.9, 1.8]} fov={60} zoom={0.9}/>
<OrbitControls target={-0.061775 , 10, 0} />
<ambientLight intensity={1} />
<spotLight intensity={1} angle={0.1} penumbra={1} position={[10, 15, 10]} castShadow />
<Suspense fallback={null}>
<Bike />
<Environment preset="city" />
<ContactShadows rotation-x={Math.PI / 2} position={[0, -0.8, 0]} opacity={0.25} width={10} height={10} blur={1.5} far={0.8} />
</Suspense>
</Canvas>
</>
)
}
I have tried to change it using target variable in OrbitControls imported from #react-three/drei but the x and y axis is not working and z axis is nuts.
Should I use anothe OrbitControl for React.Please help.
In order to change the initial target for OrbitControls, you need to wrap the prop in an array like the following:
<OrbitControls target={[-0.061775 , 10, 0]} />
thanks to r3f "Set" shortcut
Alternatively, if you wanted to declare target.x, target.y, or target.z separately, you could use the following dashed syntax:
<OrbitControls target-x={-0.061775} />
thanks to r3f "Piercing into nested properties"
Related
import { Stats,OrbitControls,Circle } from '#react-three/drei'
import { Canvas,useLoader } from '#react-three/fiber'
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'
export default function App() {
const gltf = useLoader(GLTFLoader,'./models/monkey.glb')
return (
<Canvas camera={{ position: [-0.5,1,2] }} shadows>
<directionalLight position={[3.3,1.0,4.4]} castShadow />
<primitive
object={gltf.scene}
position={[0,1,0]} />
<primitive
object={gltf.scene}
position={[0,1,0]} />
<Circle args={[10]} rotation-x={-Math.PI / 2} receiveShadow>
<meshStandardMaterial />
</Circle>
<OrbitControls target={[0,0,0]} />
<axesHelper args={[5]} />
<Stats />
</Canvas>
)
}
so I want to insert a model and want to copy it to 2, so I add 2 primitives but can't, is there any other way to duplicate the same model to 2?
I'm a beginner at Three JS and have some issues with my code. My problem is I don't get the shadow properly in every object I attached. Here's the picture:
Here's my code in the sandbox:
https://codesandbox.io/s/threejs-code-3rlk8b
import React, { Suspense, useRef } from 'react';
import { Canvas, useFrame } from '#react-three/fiber';
import { ContactShadows, OrbitControls, useGLTF } from '#react-three/drei'
import './PartOne.css';
import { RoomOne } from '../assets/Room1';
import { Room2 } from '../assets/Room2';
import { Room3 } from '../assets/Room3';
import { Room4 } from '../assets/Room4';
import { Room5 } from '../assets/Room5';
import { Room6 } from '../assets/Room6';
import { Room7 } from '../assets/Room7';
import { Room8 } from '../assets/Room8';
const PartOne = () => {
return (
<div className='wrapper' >
<Canvas shadows camera={{ fov:70, position: [0,0,30] }} >
<Suspense fallback={null} >
<ambientLight intensity={0.3} />
<directionalLight castShadow receiveShadow intensity={2} position={[80,80,80]} />
{/* <spotLight castShadow receiveShadow intensity={2} position={[80,80,80]} /> */}
<RoomOne />
<Room2 />
<Room3 />
<Room4 />
<Room5 />
<Room6 />
<Room7 />
<Room8 />
<ContactShadows />
</Suspense>
<OrbitControls enablePan={true} enableZoom={true} enableRotate={true} />
</Canvas>
</div>
)
}
export default PartOne
Please help me with this problem. Or tell me if there is any solution to get rid of it.
The default setting of the orthographic shadow camera is -5 for left and bottom and 5 for right and top (see DirectionalLightShadow). This range is not big enough for your scene. You need to adjust the view volume of the orthographic shadow camera. e.g.:
<directionalLight
castShadow receiveShadow intensity={2} position={[80,80,80]}
shadow-normalBias={0.1}
shadow-camera-left={-12}
shadow-camera-right={12}
shadow-camera-top={12}
shadow-camera-bottom={-12}
shadow-camera-near={0.5}
shadow-camera-far={200}
/>
I'm working on a website that for now, only has a text and a floating 3D logo on the right. The thing is, when I'm watching the object, the animation runs at 60fps and the website runs smoothly, but when I'm not watching the object, the website has a lot of lag and it's unusable so, I wanted to know why that happens and how I can fix it.
Here's my code:
index.js
<div className={styles.logo}>
<Suspense fallback={null}>
<Canvas gl={{antialias: true, powerPreference: 'high-performance'}} dpr={[0.8, 1.8]}>
<Logo />
<Environment background={false} files="/images/env2.hdr" near={1} far={1000} resolution={256} />
</Canvas>
</Suspense>
</div>
logo.js
export default function Logo({ ...props }) {
const group = useRef()
const { nodes, materials } = useGLTF('/images/RB_Maquillaje_2-transformed.glb')
useFrame((state) => {
const t = state.clock.getElapsedTime()
group.current.position.y = Math.sin(t) * 0.2;
group.current.rotation.y = Math.sin(t / 1.5) / 15
})
return (
<group ref={group} {...props} dispose={null}>
<motion.mesh initial={{scale: 0}} animate={{scale: 1}}
transition={{duration: 0.5, type: 'spring', stiffness: 200, damping: 20}}
geometry={nodes.BezierCurve004.geometry} material={materials['Material.001']} rotation={[0, -0.2, 0]} position={[0, -0.2, 1]} />
</group>
)
}
useGLTF.preload('/images/RB_Maquillaje_2-transformed.glb')
So I explore 2 cubes sample. I want to click only on one cube at a time. Yet when I click on a cube that has a cube right behind the current one both get clicked. How to force click and hover only on the nearest one?
In other words clicking\hovering on cube A I want cube B not to be clicked
My code sample:
import React, { useRef, useState } from 'react'
import { Canvas, useFrame } from '#react-three/fiber'
function Box(props) {
// This reference will give us direct access to the mesh
const mesh = useRef()
// Set up state for the hovered and active state
const [hovered, setHover] = useState(false)
const [active, setActive] = useState(false)
// Rotate mesh every frame, this is outside of React without overhead
useFrame(() => {
mesh.current.rotation.x = mesh.current.rotation.y += 0.01
})
return (
<mesh
{...props}
ref={mesh}
scale={active ? 1.5 : 1}
onClick={(e) => setActive(!active)}
onPointerOver={(e) => setHover(true)}
onPointerOut={(e) => setHover(false)}>
<boxGeometry args={[1, 1, 1]} />
<meshStandardMaterial color={hovered ? 'hotpink' : 'orange'} />
</mesh>
)
}
export default function App() {
return (
<Canvas>
<ambientLight intensity={0.5} />
<spotLight position={[10, 10, 10]} angle={0.15} penumbra={1} />
<pointLight position={[-10, -10, -10]} />
<Box position={[1.2, 0.5, 0]} />
<Box position={[1.2, 0, 0]} />
</Canvas>
)
}
Solved it here
main diff:
function intersectionsFilter(intersections) {
return intersections?.length ? [intersections[0]] : intersections
}
export default function App() {
return (
<Canvas raycaster={{ filter: intersectionsFilter }}>
I'm building a page with two overlapping components and i want to pass mouse events from the top component to the bottom one.
I'm using ReactJs and the code looks like this:
export default function App() {
return (
<>
<SkyBox className='Streetview' onClick={()=>console.log("you clicked STREETVIEW!")}/>
<Canvas className='Canvas' onClick={()=> console.log("you clicked THREEJS")}>
<Camera position={[0, 0, -20]} />
<ambientLight intensity={0.7} />
<spotLight position={[10, 10, 10]} angle={0.90} penumbra={1} />
<pointLight position={[-10, -10, -10]} />
<Suspense fallback={null}>
<Scene />
</Suspense>
</Canvas>
</>
);
}
so I want to get the mouse events from the Canvas component and pass them to the streetview SkyBox one so the user could navigate the streetview panorama and therefore the events i'm interested in is the mouseClick , mouseMove and mouseOut.
You can pass events as props like so:
import { useState } from 'react'
const Wrapper = () => {
const [event, setEvent] = useState(null)
return (
<div onClick={(e) => setEvent(e)}>
Lorem Ipsum
<Component event={event} />
</div>
)
}
const Component = (event) => {
console.log(event) // → event: SyntheticBaseEvent
return null
}
export default Wrapper
I'm not sure if you need the current state of the mouse-events but doesn't matter if state or the setters you can use context for this.
export const CanvasContext = createContext();
export default function App() {
const [mouseClicked, setMouseClicked] = useState(...);
const [mouseMoveState, setMouseMoveState] = useState(...);
const [mouseOut, setMouseOut] = useState(...);
return (
<CanvasContext.Provider value={{
mouseClicked,
setMouseClicked,
mouseMoveState,
setMouseMoveState,
mouseOut,
setMouseOut
}}>
<SkyBox
className="Streetview"
onClick={() => console.log("you clicked STREETVIEW!")}
/>
<Canvas
className="Canvas"
onClick={() => console.log("you clicked THREEJS")}
>
<Camera position={[0, 0, -20]} />
<ambientLight intensity={0.7} />
<spotLight position={[10, 10, 10]} angle={0.9} penumbra={1} />
<pointLight position={[-10, -10, -10]} />
<Suspense fallback={null}>
<Scene />
</Suspense>
</Canvas>
</CanvasContext.Provider>
);
}
then use inside Canvas/SkyBox/... the state/setter you need like this.
export default function Canvas() {
const {setMouseClicked, setMouseMoveState} = useContext(CanvasContext);
return (
<div>
.....
</div>
);
}