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

compatability with react-three-fiber? #85

Closed
kurosh-z opened this issue Feb 28, 2020 · 7 comments
Closed

compatability with react-three-fiber? #85

kurosh-z opened this issue Feb 28, 2020 · 7 comments

Comments

@kurosh-z
Copy link

kurosh-z commented Feb 28, 2020

hi ;)
I gave it a try with react-three-fiber and it got very laggy! specially as I try to rotate things!
here is the piece of Code that I wrote to make it work with react-three-fiber:

import React, { useRef } from 'react';
import * as THREE from 'three';
import { ReactThreeFiber, extend, useFrame, useThree } from 'react-three-fiber';
import CameraControls from 'camera-controls';
CameraControls.install({ THREE: THREE });

extend({ CameraControls });

declare global {
  namespace JSX {
    interface IntrinsicElements {
      cameraControls: ReactThreeFiber.Object3DNode<
        CameraControls,
        typeof CameraControls
      >;
    }
  }
}

const CControls: React.FC<any> = () => {
  const ccontrolRef = useRef<any>(null);
  const { camera, gl, clock, scene } = useThree();
  useFrame(() => {
    if (ccontrolRef.current) {
      const delta = clock.getDelta();
      const hasControlsUpdated = ccontrolRef.current.update(delta);
      if (hasControlsUpdated) gl.render(scene, camera);
    }
  });
  return <cameraControls ref={ccontrolRef} args={[camera, gl.domElement]} />;
};

export default CControls;

am I doing something wrong here? or its not somehow compatible with react-three?

@yomotsu
Copy link
Owner

yomotsu commented Feb 28, 2020

Did you try without camera controls?
Did you also try with threejs official orbit controls?

Then if still it happens, can you provide a simplified working example on jsfiddle or somewhere? Otherwise I need to prepare the environment to reproduce.

@kurosh-z
Copy link
Author

Thank you for the speedy reply!
yes I have used OrbitControls and it works fine!
here is the codesanbox version with some simplifications. you can click on the button to switch the controllers.
https://codesandbox.io/s/blissful-chandrasekhar-ew99r

@yomotsu
Copy link
Owner

yomotsu commented Feb 29, 2020

Seems delta of every frame in your app is too small. delta is supposed to be 0.01666... sec or so.
Screen Shot 2020-02-29 at 10 52 27 AM

You can use getElapsedTime() to get correct delta, rather than getDelta().

const CControls: React.FC<any> = () => {
  const ccontrolRef = useRef<any>(null);
  const { camera, gl, clock, scene } = useThree();
  let lastTime = 0;
  useFrame(() => {
    if (ccontrolRef.current) {
      const elapsed = clock.getElapsedTime();
      const delta = elapsed - lastTime;
      console.log( delta );
      //   ccontrolRef.current.update();
      const hasControlsUpdated = ccontrolRef.current.update(delta);
      if (hasControlsUpdated) gl.render(scene, camera);

      lastTime = elapsed;
    }
  });
  return <cameraControls ref={ccontrolRef} args={[camera, gl.domElement]} />;
};

If you call getDelta() somewhere else, the delta time will be the diff between "somewhere" and the useFrame.
I think this is not a problem of camera-controls.

@kurosh-z
Copy link
Author

I don't know about internals of react-three-fiber but I don't use getDelta() in my app yet!
anyway that definitely solved the problem!
thanks again for investigating the issue.

@yomotsu yomotsu closed this as completed Feb 29, 2020
@jfabraxas
Copy link

FYI: Second arg of useFrame callback is delta:

 useFrame((state, delta) => {
    if (ccontrolRef.current) {
      const hasControlsUpdated = ccontrolRef.current.update(delta);
      if (hasControlsUpdated) gl.render(scene, camera);
    }
  });

rf3 doc

@lujeff lujeff mentioned this issue Oct 3, 2020
@yaroslavnikiforov
Copy link

You don't need this line:
if (hasControlsUpdated) gl.render(scene, camera);

@ammanvedi
Copy link

just got this working here is my final code, seems to be working nicely thank you to both above i was trying to get a nice solution for dollyToCursor with OrbitControls with no luck and this one is perfect, i can go to bed now XD

import React from 'react';
import * as THREE from 'three';
import { extend, ReactThreeFiber, useFrame, useThree } from '@react-three/fiber';
import CameraControls from 'camera-controls';

CameraControls.install({ THREE: THREE });

extend({ CameraControls });

declare global {
    namespace JSX {
        interface IntrinsicElements {
            cameraControls: ReactThreeFiber.Object3DNode<
                CameraControls,
                typeof CameraControls
            >;
        }
    }
}

export const CustomOrbitControls: React.FC<any> = React.forwardRef((props, ref) => {
    const { camera, gl } = useThree();
    useFrame((state, delta) => {
        if (ref.current) {
            ref.current.update(delta);
        }
    });
    return (
        <cameraControls
            ref={ref}
            args={[camera, gl.domElement]}
            dollyToCursor
            mouseButtons={{
                left: CameraControls.ACTION.TRUCK,
                middle: CameraControls.ACTION.NONE,
                right: CameraControls.ACTION.NONE,
                shiftLeft: CameraControls.ACTION.NONE,
                wheel: CameraControls.ACTION.ZOOM,
            }}
        />
    );
});

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

5 participants