Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

component variables access inside hooks. #165

Open
sancelot opened this issue Nov 9, 2021 · 1 comment
Open

component variables access inside hooks. #165

sancelot opened this issue Nov 9, 2021 · 1 comment

Comments

@sancelot
Copy link

sancelot commented Nov 9, 2021

I am trying to use correctly hooks with a 3d scene widget. I really don't understand how to deal with component variables

A 3d scene is created in useEffect() , that is fired only once. Some component variables are created , like scene, camera , camera controls inside useEffect()
I will later need some references to these variable , camera or camera controls variable (eg, to zoom thanks an ui slider).

in this component example, a zoom value is changed thanks to an external zoom ui slider ,
I can retrieve the zoom value thanks to redux store .

I am notified of this change with useMemo zoomChanged function .
first question : why zoomChanged does not work with a useCallback instead of useMemo ????

second question, how can I access to component variables controls or camera inside zoomChanged function ? they are undefined when zoomChanged is fired.


import React, {
    MutableRefObject,
    ReactElement,
    useCallback,
    useEffect,
    useLayoutEffect,
    useMemo,
    useRef,
    useState
} from 'react';
import { useSelector } from 'react-redux';

import * as THREE from 'three';
import { DDSLoader } from 'three/examples/jsm/loaders/DDSLoader';

import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
import { PlayerBtn } from './sub_components/PlayerBtn';
import { SliderSpeed } from './sub_components/SliderSpeed';
import { SliderTimeline } from './sub_components/SliderTimeline';
import { SliderZoom } from './sub_components/SliderZoom';

import { RootState } from 'store';

import { Button } from 'primereact/button';
import { Toast } from 'primereact/toast';

import 'styles/SceneComponent.css';
import { DirectionalLight } from 'three';
import { RoomEnvironment } from 'three/examples//jsm/environments/RoomEnvironment';

type Props = {
    antialias?: boolean;
    engineOptions?: undefined; // FIXME
    adaptToDeviceRatio?: boolean;
    sceneOptions?: undefined; // FIXME
    onSceneReady: (scene: THREE.Scene) => void;
    onRender?: (scene: THREE.Scene) => void;
    id: string;
    mainLoop: (scene: THREE.Scene, setActualAxisState: (map: { [key: string]: number }) => void) => void;
    setActualAxisState: (map: { [key: string]: number }) => void;
};
type Nullable<T> = T | null;

export const SceneComponent = (props: Props): ReactElement => {
    const reactCanvas = useRef<HTMLCanvasElement>(null); // useRef<Nullable<HTMLCanvasElement>>(null);

    const zoom = useSelector((state: RootState) => state.simul_data.zoom);
    const [CameraZoom, setCameraZoom] = useState(0);
    let scene: THREE.Scene;
    let camera: THREE.PerspectiveCamera;
    let renderer: THREE.WebGLRenderer;
    let controls: OrbitControls | undefined;

    const {
        antialias,
        engineOptions,
        adaptToDeviceRatio,
        sceneOptions,
        onRender,
        onSceneReady,
        mainLoop,
        setActualAxisState,
        ...rest
    } = props;

    function RenderScene() {
        if (controls) {
            controls.update();
            controls.minDistance = 50;
            controls.maxDistance = 2000;

            const zoom = controls.target.distanceTo(controls.object.position);
            console.log('min distance ', controls.minDistance);
            console.log('max distance ', controls.maxDistance);
            console.log('distance ', zoom);
        }
        renderer.render(scene, camera);
    }

    useEffect(() => {
        // "This only happens ONCE.  But it happens AFTER the initial render."
        if (reactCanvas.current) {
            const width = reactCanvas.current.clientWidth;
            const height = reactCanvas.current.clientHeight;

            scene = new THREE.Scene();

            camera = new THREE.PerspectiveCamera(75, width / height, 1, 10000);
            camera.position.set(0, 0, 2000);
            renderer = new THREE.WebGLRenderer({ canvas: reactCanvas.current, antialias: true });
            controls = new OrbitControls(camera, renderer.domElement);

            controls.update();

          
            renderer.toneMapping = THREE.ACESFilmicToneMapping;
            renderer.toneMappingExposure = 1;
            renderer.outputEncoding = THREE.sRGBEncoding;

            const pmremGenerator = new THREE.PMREMGenerator(renderer);
            scene.environment = pmremGenerator.fromScene(new RoomEnvironment()).texture;

      
            renderer.setClearColor('#196696');
            renderer.setSize(width, height, true);

            
            const startRenderLoop = (e: Event) => {
                console.log('start render loop');
                // start the loop
                renderer.setAnimationLoop(() => {
                    console.log('render it');
                    RenderScene();
                });
            };
            const stopRenderLoop = (e: Event) => {
                console.log('stop render loop');
                renderer.setAnimationLoop(null);
            };
            const wheel = (e: Event) => {
                console.log('change render loop');
                renderer.setAnimationLoop(null);
            };
            controls.addEventListener('start', startRenderLoop);
            controls.addEventListener('end', stopRenderLoop);
            controls.addEventListener('change', startRenderLoop);

            props.mainLoop(scene, setActualAxisState);

            const handleResize = () => {
                if (reactCanvas.current) {
                    console.log('handleresize');
                    const width = reactCanvas.current.clientWidth;
                    const height = reactCanvas.current.clientHeight;
                    renderer.setSize(width, height);
                    camera.aspect = width / height;
                    camera.updateProjectionMatrix();
                    if (controls) controls.update();
                    RenderScene();
                }
            };

            const onMouseWheel = () => {
                RenderScene();
            };

            if (window) {
                window.addEventListener('resize', handleResize);
                window.addEventListener('wheel', onMouseWheel, { passive: false });
            }

            // animate();
            return () => {
                window.removeEventListener('resize', handleResize);
                window.removeEventListener('wheel', onMouseWheel);
                renderer.dispose();
            };
        }
        // eslint-disable-next-line react-hooks/exhaustive-deps
    }, []);

    const zoomMe = () => {
    };

    const zoomChanged = useMemo(() => {
        console.log('zoom has changed', zoom);
        console.log('controls variable ', controls);
        if (controls) {
            const MaxDistance = 2000;
            const MinDistance = 50;
            const delta = MaxDistance - MinDistance;

            const zoomDistance = MinDistance + (delta * zoom) / 100;
            const currDistance = camera.position.length();
            const factor = zoomDistance / currDistance;
            console.log('z factor', factor);
            controls.object.position.x *= factor;
            controls.object.position.y *= factor;
            controls.object.position.z *= factor;
            controls.update();
            //controls.dollyOut(zoom);
            if (renderer) RenderScene();
        }
        // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [zoom]);


    return (
        <div className='scene-component'>
            <canvas className='canvas-holder' ref={reactCanvas} {...rest} />
        </div>
    );
};

@Whoaa512
Copy link

Whoaa512 commented Nov 9, 2021

Please try asking on https://stackoverflow.com/

Dan's AMA repo is not meant for personal debugging help

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants