I was just reading up on babylon native on a medium post ( Babylon React Native: Bringing 3D and XR to React Native Applications | by Babylon.js | Medium) by @ryantrem
Specifically:
We also have some aspirations around declarative scene definitions using JSX (similar to GitHub - brianzinn/react-babylonjs: React for Babylon 3D engine) as React Native has some great fast refresh optimizations when only JSX is changed, but no concrete plans here yet.
The template I am comparing to below is here:
BabylonReactNative/App.tsx at master · BabylonJS/BabylonReactNative (github.com)
So, I was able to quite quickly get it working. One thing I noticed was it allowed me reduce the template code in some parts. I didn’t need hooks to track instances - look at how I scale the transform node (I do not need to track the transform node instance or require a useEffect to apply the scaling) - react-reconciler
does that via the renderer. It would work the same with the Model
and a useBeforeRender
hook to match the original template - just experimenting here…
Full code:
/**
* Modified the TypeScript template
* https://github.com/react-native-community/react-native-template-typescript
*/
import React, { useState, FunctionComponent, useEffect, useCallback } from 'react';
import { SafeAreaView, StatusBar, Button, View, Text, ViewProps, Image } from 'react-native';
import { EngineView, useEngine } from '@babylonjs/react-native';
import { Camera, Vector3, Color3, TransformNode } from '@babylonjs/core';
import { EngineCanvasContext, Scene } from 'react-babylonjs';
import Slider from '@react-native-community/slider';
const EngineScreen: FunctionComponent<ViewProps> = (props: ViewProps) => {
const defaultScale = 1;
const engine = useEngine();
const [toggleView, setToggleView] = useState(false);
const [camera, setCamera] = useState<Camera>();
const [scale, setScale] = useState<number>(defaultScale);
return (
<>
<View style={props.style}>
<Button title="Toggle EngineView" onPress={() => { setToggleView(!toggleView) }} />
{ !toggleView &&
<View style={{flex: 1}}>
<EngineCanvasContext.Provider value={{ engine, canvas: null }}>
{engine &&
<Scene>
<arcRotateCamera
name="camera1"
onCreated={camera => setCamera(camera)}
target={Vector3.Zero()}
alpha={Math.PI / 2}
beta={Math.PI / 4}
radius={8}
/>
<hemisphericLight
name="light1"
intensity={0.7}
direction={Vector3.Up()}
/>
<transformNode name='Root Container' scaling={new Vector3(scale, scale, scale)}>
<icoSphere
name={"ico"}
radius={0.2}
flat
subdivisions={1}
>
<standardMaterial
name={'ico-mat'}
diffuseColor={Color3.Red()}
specularColor={Color3.Black()}
/>
</icoSphere>
</transformNode>
</Scene>
}
</EngineCanvasContext.Provider>
<EngineView camera={camera} displayFrameRate={true} />
<Slider style={{position: 'absolute', minHeight: 50, margin: 10, left: 0, right: 0, bottom: 0}} minimumValue={0.2} maximumValue={2} step={0.01} value={defaultScale} onValueChange={setScale} />
<Text style={{color: 'yellow', position: 'absolute', margin: 3}}>react-babylonjs</Text>
</View>
}
{ toggleView &&
<View style={{flex: 1, justifyContent: 'center', alignItems: 'center'}}>
<Text style={{fontSize: 24}}>EngineView has been removed.</Text>
<Text style={{fontSize: 12}}>Render loop stopped, but engine is still alive.</Text>
</View>
}
</View>
</>
);
};
There is a new react-babylonjs
website coming out for 5.0 - will be adding recipes like this and more. Just need to make some time!! The new website is cool, because all the samples open in code sandbox and will be easy to contribute content via markdown - on the site itself you can switch between the running sample and code (much like our sandbox), but it also has javascript and typescript for all examples automatically via transpiling. Looking forward to rolling that out soon.
edit: tried to change code to jsx syntax, but looks like it doesn’t work