Is it possible to define the hello function
function onSceneReady(scene: Scene) {
const box = BABYLON.MeshBuilder.CreateBox("box", {size: 2}, scene);
box.position.z = 3;
}
export default class Viewer extends Component {
render() {
return (
<Engine antialias adaptToDeviceRatio width={window.innerWidth} height={window.innerHeight}>
<Scene>
<arcRotateCamera name='camera1' alpha={Math.PI / 2} beta={Math.PI / 4} radius={2.0} target={new Vector3(0, 0, 0)} />
<hemisphericLight name='light1' intensity={0.7} direction={Vector3.Up()} />
{onSceneReady}
</Scene>
</Engine>
)
}
}
1 Like
I’m not sure what you mean by “the hello function”. I’m assuming you are using react-babylonJS? @brianzinn may be able to help if the question is more clear. 
2 Likes
The renderer will complain when you try to have {onSceneReady}
declared like that (you should see an error in the console).
Yes, you can call a function when the scene is ready, though! 
import { MeshBuilder } from '@babylonjs/core';
import { Scene, Engine, SceneEventArgs } from 'react-babylonjs';
function onSceneReady(e: SceneEventArgs) {
const box = MeshBuilder.CreateBox("box", {size: 2}, e.scene);
box.position.z = 3;
};
class YourComponent extends React.Component {
render() {
return (
<Engine antialias adaptToDeviceRatio width={window.innerWidth} height={window.innerHeight}>
<Scene onSceneMount={onSceneReady}>
<arcRotateCamera name='camera1' alpha={Math.PI / 2} beta={Math.PI / 4} radius={2.0} target={new Vector3(0, 0, 0)} />
<hemisphericLight name='light1' intensity={0.7} direction={Vector3.Up()} />
</Scene>
</Engine>
)
}
- I would recommend to switch all of your packages to
@babylonjs/core
, etc (the ES6 ones)
- You can use
<box position={new Vector3(0, 0, 2)} size={2} />
for declarative, but I suspect you are experimenting in another way.
- There is a
useScene
hook that you can use inside of the <Scene ../>
component, if you want the scene available inside your component tree.
Keep asking questions - it’s the best way to learn!
1 Like
I could not complete more than one function
import React, { Component } from 'react';
import { Scene, Engine, Box, Sphere, SceneEventArgs, useScene} from 'react-babylonjs';
import { Vector3, MeshBuilder, FreeCamera, HemisphericLight ,Color3} from '@babylonjs/core';
function onSphere(e: SceneEventArgs) {
const box = MeshBuilder.CreateSphere("sphere", {size: 2}, e.scene);
box.position.y = 1;
}
function onSceneReady(e: SceneEventArgs) {
const box = MeshBuilder.CreateBox("box", {size: 2}, e.scene);
}
export default class Viewer extends Component {
render() {
return (
<Engine antialias adaptToDeviceRatio width={window.innerWidth} height={window.innerHeight}>
<Scene onSceneMount={onSphere} onSceneMount={onSceneReady}>
<arcRotateCamera name='camera1' alpha={Math.PI / 2} beta={Math.PI / 4} radius={7.0} target={new Vector3(0, 0, 0)} />
<hemisphericLight name='light1' intensity={0.7} direction={Vector3.Up()} />
</Scene>
</Engine>
)
}
}
My 2nd problem
Viewed.js
import React, { Component } from 'react';
import { Scene, Engine, Box, Sphere, SceneEventArgs, useScene} from 'react-babylonjs';
import { Vector3, MeshBuilder, FreeCamera, HemisphericLight ,Color3} from '@babylonjs/core';
import Sphere from './sphere':
function onSphere(e: SceneEventArgs) {
const box = MeshBuilder.CreateSphere("sphere", {size: 2}, e.scene);
box.position.y = 1;
}
function onSceneReady(e: SceneEventArgs) {
const box = MeshBuilder.CreateBox("box", {size: 2}, e.scene);
}
export default class Viewer extends Component {
render() {
return (
<Engine antialias adaptToDeviceRatio width={window.innerWidth} height={window.innerHeight}>
<Scene onSceneMount={onSphere} onSceneMount={onSceneReady}>
<arcRotateCamera name='camera1' alpha={Math.PI / 2} beta={Math.PI / 4} radius={7.0} target={new Vector3(0, 0, 0)} />
<hemisphericLight name='light1' intensity={0.7} direction={Vector3.Up()} />
<Sphere />
</Scene>
</Engine>
)
}
}
Sphere.js
import React, { Component } from 'react';
import { Scene, Engine, SphereCylinder,SceneEventArgs, useScene} from 'react-babylonjs';
import { MeshBuilder} from '@babylonjs/core';
function onSphere(e: SceneEventArgs) {
const box = MeshBuilder.CreateSphere("sphere", {size: 2}, e.scene);
box.position.y = 1;
}
export default class Sphere extends Component {
render() {
return (
<Scene onSceneMount={onSphere}>
)
}
}
I could not solve the problem
thank you in advance for help
hi @3dObject ,
I don’t really know what the reconciler would do when you send the same prop twice. You could get around that by having a single function that calls other functions:
function createBox(e: SceneEventArgs) {
const box = MeshBuilder.CreateBox("box", {size: 2}, e.scene);
}
function createSphere(e: SceneEventArgs) {
const sphere = MeshBuilder.CreateSphere("sphere", {size: 2}, e.scene);
sphere.position.y = 1;
}
function function onSceneReady(e: SceneEventArgs) {
createBox(e);
createSphere(e);
}
....
<Scene onSceneMount={onSceneMount} />
I would probably discourage using the onSceneMount
that way for a few reasons:
- You are not creating your scene graph in a way that you can compose your scene and track your objects in components.
- If you are building your project that way you don’t get any of the benefits of
react-babylonjs
with declarative scene composition or re-usable components.
Also, you have a nested <Scene />
in your Sphere
component. Try to think of the Scene as typically you have 1 engine and 1 scene. There are special cases where you would have multiple scenes. You can access the babylon Scene object anywhere in the component tree with the hook useScene
.
Your Sphere
component could just be:
export default class MySphere extends Component {
render(props) {
return (
<sphere diameter={props.diameter} />
)
}
}
You can pass now diameter to your MySphere
class.
<Scene .... >
... lights/camera/etc.
<MySphere diameter={2} />
</Scene>
It’s a lot of concepts to be connecting React and how Babylonjs works. Feel free to ask more questions or provide a more concrete example - it’s hard to see in trivial examples what you are trying to accomplish. The repo main readme has some composition examples, but isn’t using classes extending React.Component, but instead functional components.
1 Like
Hello @brianzinn
How can I complete MyBox here
function MyBox(e: SceneEventArgs) {
const box = MeshBuilder.CreateSphere("sphere", {size: 2}, e.scene);
box.position.y = 3;
}
export default class MySphere extends Component {
render(props) {
return (
<>
MyBox(e);
<sphere diameter={props.diameter} />
</>
)
}
}
hi @3dObject,
Here is how I would do that in a react Component using a react Fragment to combine shapes:
export default class MyShapes extends Component {
render(props) {
return (
<>
<box name='box' size={2} />
<sphere diameter={props.diameter} />
</>
)
}
}
If you can show a more real life example then I could maybe work out where you are getting caught up. If you really want to use the MeshBuilder, you could try something like this
(just free-typing and untested):
import React, { useState } from 'react';
import { useScene } from 'react-babylonjs';
const MyBox = ({positionY}) => {
const scene = useScene();
const box = useState(() => {
const box = MeshBuilder.CreateBox("box", {size: 2}, scene);
box.position.y = positionY;
});
// at this point you can return null, but if you want access to it again:
// disposeInstanceOnUnmount will call dispose on the mesh, it's an opt-in feature
// otherwise you would want to use a useEffect hook or otherwise to dispose (or `onUnmount` lifecycle from React.Component
// and you also don't need to set the position.y above
return <abstractMesh fromInstance={box} position-y={positionY} disposeInstanceOnUnmount
/>
}
i want to do
app.js
import React, { Component } from 'react';
import { Scene, Engine, Box, Sphere, SceneEventArgs, useScene} from 'react-babylonjs';
import { Vector3, MeshBuilder, FreeCamera, HemisphericLight ,Color3} from '@babylonjs/core';
import MySphere from './MySphere';
function onSceneReady(e: SceneEventArgs) {
const box = MeshBuilder.CreateBox("box", {size: 2}, e.scene);
<MySphere />
}
export default class Viewer extends Component {
render() {
return (
<Engine antialias adaptToDeviceRatio width={window.innerWidth} height={window.innerHeight}>
<Scene onSceneMount={onSceneReady}>
<arcRotateCamera name='camera1' alpha={Math.PI / 2} beta={Math.PI / 4} radius={7.0} target={new Vector3(0, 0, 0)} />
<hemisphericLight name='light1' intensity={0.7} direction={Vector3.Up()} />
</Scene>
</Engine>
)
}
}
MySphere.js
import React, { Component } from 'react';
import { Scene, Engine, SphereCylinder,SceneEventArgs, useScene, onSceneMount} from 'react-babylonjs';
import { MeshBuilder} from '@babylonjs/core';
export default function MySphere(e: SceneEventArgs) {
const sphere = MeshBuilder.CreateSphere("sphere", {size: 2}, e.scene);
sphere.position.x = 1;
}
You cannot do that in React (not with DOM either) - it is just a function being called, so cannot return jsx and I am confused what you are trying to do. Your function is not possible:
function onSceneReady(e: SceneEventArgs) {
const box = MeshBuilder.CreateBox("box", {size: 2}, e.scene);
<MySphere />
}
To help you visualize - what you are writing in React DOM would look perhaps like this and is not possible:
function onClick(e) {
const box = ...
// this next line is not possible and is not valid syntax. You cannot return jsx here either.
<MySphere />
}
...
<button onClick={onClick} />
A <div />
or Component in DOM can only be “returned” in a render method or functional component returned as jsx, but simply declaring it in a function as you have done is not possible. Inside the <Scene />
you can return anything from babylon - like <box />
or <freeCamera />
, etc. My previous post showed you how I would declaratively build and also how it could be build imperatively. I would not use “onSceneReady” at all as I mentioned before - it’s just a way to provide access to Scene when it is ready, not so much for building out your scene graph.
hi @3dObject I’ve made you a code sandbox. Make changes there and let me know where you are stuck. It’s just making a couple of shapes and uses some hooks. It’s the same as the example from the homepage readme.
tender-rosalind-k11tu - CodeSandbox
thank you very much for help
here you have answered the entire answer that concerns me
I will get back to you if there is a problem
1 Like