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

Crash when trying to animate with transform props #269

Open
thiagobrez opened this issue Sep 18, 2024 · 2 comments
Open

Crash when trying to animate with transform props #269

thiagobrez opened this issue Sep 18, 2024 · 2 comments

Comments

@thiagobrez
Copy link

Hey! I've been playing with the lib, awesome work!!

I noticed that whenever I try to animate the transform props according to the docs the app crashes, on both iOS and Android.

But on the other hand, animating imperatively with TransformManager seems to work great!

Here's a minimal reproduction on a new bare RN app: https://github.com/thiagobrez/filament-crash-repro

It's a very trivial scene:

export default function BalloonsScene() {
  const translate = useSharedValue<Float3>([0, 0, 0]);

  const renderCallback: RenderCallback = useCallback(() => {
    'worklet';
    const newY = translate.value[1] + 0.01;
    translate.value = [0, newY, 0]; // Commenting this line will stop the app from crashing
  }, [translate]);

  return (
    <FilamentView style={styles.filamentView} renderCallback={renderCallback}>
      <DefaultLight />
      <Model source={BalloonModel} transformToUnitCube translate={translate} />
      <Camera />
    </FilamentView>
  );
}
Xcode logs

In the debugger: filament.render.queue (20): EXC_BAD_ACCESS (code=1, address=0x88)

In the console:

Running application filamentTranslate ({
    initialProps =     {
        concurrentRoot = 0;
    };
    rootTag = 1;
})
nw_socket_handle_socket_event [C4.1.1:1] Socket SO_ERROR [61: Connection refused]
nw_socket_handle_socket_event [C4.1.2:1] Socket SO_ERROR [61: Connection refused]
nw_connection_get_connected_socket_block_invoke [C4] Client called nw_connection_get_connected_socket on unconnected nw_connection
TCP Conn 0x60000337aee0 Failed : error 0:61 [61]
Unbalanced calls start/end for tag 19
Running "filamentTranslate" with {"rootTag":1,"initialProps":{"concurrentRoot":false}}
[RNF/Dispatcher]: Installing global Dispatcher Holder...
[RNF/WorkletRuntimeCollector]: Registering WorkletRuntime 0x600002609c98
[RNF/HybridObject]: (MEMORY) Creating FilamentProxy (#1)... ✅
Loading react-native-worklets-core...
Worklets loaded successfully
[RNF/FilamentProxy]: Creating Worklet Context...
Incorrect NSStringEncoding value 0x8000100 detected. Assuming NSASCIIStringEncoding. Will stop this compatibility mapping behavior in the near future.
[RNF/FilamentProxy]: Successfully created WorkletContext! Installing global Dispatcher...
[RNF/Dispatcher]: Installing global Dispatcher Holder...
[RNF/WorkletRuntimeCollector]: Registering WorkletRuntime 0x600003505ef0
[RNF/FilamentProxy]: Successfully installed global Dispatcher in WorkletContext!
[RNF/FilamentProxy]: Creating Engine...
FEngine (64 bits) created at 0x10da97e00 (threading is enabled)
FEngine resolved backend: Metal
Selected physical device 'Apple iOS simulator GPU'
Backend feature level: 2
FEngine feature level: 1
[RNF/FilamentProxy]: Display refresh rate: 60.000000 Hz
[RNF/HybridObject]: (MEMORY) Creating EngineWrapper (#1)... ✅
[RNF/FilamentProxy]: Creating Choreographer...
[RNF/HybridObject]: (MEMORY) Creating ChoreographerWrapper (#1)... ✅
[RNF/HybridObject]: (MEMORY) Creating TransformManagerWrapper (#1)... ✅
[RNF/HybridObject]: (MEMORY) Creating RenderableManagerWrapper (#1)... ✅
[RNF/HybridObject]: (MEMORY) Creating SceneWrapper (#1)... ✅
[RNF/HybridObject]: (MEMORY) Creating LightManager (#1)... ✅
[RNF/HybridObject]: (MEMORY) Creating ViewWrapper (#1)... ✅
[RNF/HybridObject]: (MEMORY) Creating CameraWrapper (#1)... ✅
[RNF/HybridObject]: (MEMORY) Creating RendererWrapper (#1)... ✅
[RNF/HybridObject]: (MEMORY) Creating NameComponentManagerWrapper (#1)... ✅
[RNF/HybridObject]: (MEMORY) Creating EntityWrapper (#1)... ✅
[RNF/FilamentProxy]: Loading asset RNF_default_env_ibl.ktx...
[RNF/HybridObject]: (MEMORY) Creating FilamentBuffer (#1)... ✅
[RNF/FilamentProxy]: Loading asset http://localhost:8081/assets/src/balloon.glb?platform=ios&hash=a8264637d75085ee73683ccc41a3e40f...
[RNF/AppleFilamentProxy]: Fetching http://localhost:8081/assets/src/balloon.glb?platform=ios&hash=a8264637d75085ee73683ccc41a3e40f...
[RNF/FilamentProxy]: Finding FilamentView #13...
[RNF/HybridObject]: (MEMORY) Creating FilamentView (#1)... ✅
[RNF/HybridObject]: (MEMORY) Creating SurfaceProvider (#1)... ✅
[RNF/HybridObject]: (MEMORY) Creating Surface (#1)... ✅
[RNF/SurfaceProvider]: Surface created!
[RNF/HybridObject]: (MEMORY) Creating Listener (#1)... ✅
[RNF/Listener]: Creating Listener...
[RNF/SurfaceProvider]: Adding "surface created" listener
[RNF/HybridObject]: (MEMORY) Creating Listener (#2)... ✅
[RNF/Listener]: Creating Listener...
[RNF/SurfaceProvider]: Adding "surface destroyed" listener
[RNF/HybridObject]: (MEMORY) Creating Listener (#3)... ✅
[RNF/Listener]: Creating Listener...
[RNF/EngineImpl]: Setting surface provider...
[RNF/PointerHolder]: Manually releasing FilamentBuffer... (PointerHolder::release())
[RNF/HybridObject]: (MEMORY) Creating Listener (#4)... ✅
[RNF/Listener]: Creating Listener...
[RNF/EngineWrapper]: Creating swapchain for surface ...
[RNF/EngineImpl]: Creating swapchain ...
[RNF/HybridObject]: (MEMORY) Creating SwapChainWrapper (#1)... ✅
[RNF/EngineImpl]: Setting swapchain...
[RNF/ChoreographerWrapper]: Adding frame callback listener
[RNF/HybridObject]: (MEMORY) Creating Listener (#5)... ✅
[RNF/Listener]: Creating Listener...
Starting choreographer
[RNF/HybridObject]: (MEMORY) Creating FilamentBuffer (#2)... ✅
[RNF/HybridObject]: (MEMORY) Creating FilamentAssetWrapper (#1)... ✅
[RNF/PointerHolder]: Manually releasing FilamentBuffer... (PointerHolder::release())
[RNF/HybridObject]: (MEMORY) Creating AABBWrapper (#1)... ✅
[RNF/HybridObject]: (MEMORY) Creating EntityWrapper (#2)... ✅
[RNF/HybridObject]: (MEMORY) Creating FilamentInstanceWrapper (#1)... ✅
[RNF/HybridObject]: (MEMORY) Creating EntityWrapper (#3)... ✅
[RNF/HybridObject]: (MEMORY) Creating EntityWrapper (#4)... ✅
'Setting up camera lens with aspect ratio:', 0.4612676056338028
Warning: sample comparison not supported by this GPU

I guess I can continue with TransformManager for now, but just wanted let you know 👍🏻

@xleddyl
Copy link

xleddyl commented Dec 7, 2024

same issue

@kuro-mekami
Copy link

kuro-mekami commented Jan 12, 2025

Hey,

I investigated this problem some time ago. I encountered the same crashes and also switched to the imperative approach. But later, when I wanted to clean up the code and make it more declarative and in line with the components from the library, I started looking into this and found the problem (but still kept my imperative approach in the end).

The issue seems to be here: package/src/hooks/internal/useApplyTransformations.tsx

transformManager.setEntityPosition(entity, position.value, multiplyWithCurrentTransform)

Using position.value doesn’t seem to work as expected. However, using [position.value[0], position.value[1], position.value[2]] fixes the issue.

Also, I think replacing useEffect with useWorkletEffect seems to be necessary. At least, this is what I changed in my code to get it working, based on the snippets I have lying around from when I worked on this. I remember playing around with useEffect and useWorkletEffect in this hook and noticing some differences. For example, I think there were crashes when reloading the app with one of those approaches. I also noticed an issue when reloading while the transform prop was actively changing—it seemed to crash in that case. However, it worked fine when the updates were paused before reloading.

I’m not entirely sure anymore which approach (useEffect or useWorkletEffect) is better in which situation, and I couldn’t completely understand why one was used over the other in some parts of the hook. But in my case, replacing it with useWorkletEffect worked and resolved the issue.

Here’s the original code (lines 108–120):

useEffect(() => {
  if (entity == null) return;

  if (position == null || Array.isArray(position)) return;

  const unsubscribePosition = position.addListener(() => {
    transformManager.setEntityPosition(entity, position.value, multiplyWithCurrentTransform);
  });

  return () => {
    unsubscribePosition();
  };
}, [entity, multiplyWithCurrentTransform, position, transformManager]);

Replacing it with this:

useWorkletEffect(() => {
  'worklet';

  if (entity == null) return;

  if (position == null || Array.isArray(position)) {
    return;
  }

  const unsubscribePosition = position.addListener(() => {
    'worklet';

    transformManager.setEntityPosition(
      entity,
      [position.value[0], position.value[1], position.value[2]],
      multiplyWithCurrentTransform
    );
  });

  return () => {
    'worklet';
    unsubscribePosition();
  };
});

worked for me.

Also, I made similar adjustments for the scaling values in lines 71 to 83, following the same approach as for the position described above. Without these changes, the scale prop was also causing crashes. With these adjustments, the scale prop worked as expected as well.

This resolved the crashes and allowed me to use the declarative API as intended. However, I can’t say for sure if this approach works perfectly in the long run, as I decided to stick with my imperative approach. Hope this helps :)

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

3 participants