Closed DenysAshikhin closed 5 months ago
The Model component doesn’t do much. Just a wrapper for a scene loader hook: https://github.com/brianzinn/react-babylonjs/blob/master/packages/react-babylonjs/src/customComponents/Model.tsx#L55
If you have captured that mesh reference then you can declaratively use “InstancedMesh” or create instance yourself and use “fromInstance” prop on a “Mesh”. Don’t let the name of the property mislead you as it is available on ALL declared types.
So I used the
<Model
onLoad={(root_mesh)=>{
root_mesh_ref.current = root_mesh}
}
/Model>
Then later:
{root_mesh_ref.current && (
<Mesh
fromInstance={root_mesh_ref.current.rootMesh}
/>
)
Except I get:
ReactBabylonJSHostConfig.ts:481 fromInstance wrong type. AbstractMesh {_isDirty: true, _nodeDataStorage: _InternalNodeDataInfo, state: '', metadata: null, reservedDataStore: null, …} class Mesh extends _abstractMesh_js__WEBPACK_IMPORTED_MODULE_13__.AbstractMesh {
/**
* @constructor
* @param name The value used by scene.getMeshByName() to do a lookup.
* @param scene The scene…
at Mesh
at Suspense
at CoreModel (http://localhost:3000/static/js/src_assets_3d_icon_svg-src_assets_Exit_Fullscreen_svg-src_assets_Fullscreen_svg-src_assets_Ma-1115ee.chunk.js:7805:5)
Am I doing it wrong?
Swapping to abstractMesh leads to no errors, but no model or anything shows up
<abstractMesh
fromInstance={cavity_block_ref.current.rootMesh}
position={new Vector3(10, 10, 10)}
name={`core_block.glb?id=${3132132133115}-model`}
/>
However, if I try to use: instancedMesh
I get the following:
<instancedMesh
fromInstance={cavity_block_ref.current.rootMesh}
position={new Vector3(10, 10, 10)}
name={`core_block.glb?id=${3132132133115}-model`}
/>
instancedMesh.ts:46 Uncaught TypeError: Cannot read properties of undefined (reading 'getScene')
at new InstancedMesh (instancedMesh.ts:46:1)
at createInstance (ReactBabylonJSHostConfig.ts:550:1)
at completeWork (react-reconciler.development.js:10851:1)
at completeUnitOfWork (react-reconciler.development.js:18725:1)
at performUnitOfWork (react-reconciler.development.js:18697:1)
at workLoopSync (react-reconciler.development.js:18597:1)
at renderRootSync (react-reconciler.development.js:18565:1)
at recoverFromConcurrentError (react-reconciler.development.js:17948:1)
at performSyncWorkOnRoot (react-reconciler.development.js:18194:1)
at flushSyncCallbacks (react-reconciler.development.js:2936:1)
hi, sorry i didn't notice a reply.
For the abstract mesh. I would expect it to move the position of the loaded model, if that was the last positional update. You may want to be specific with the prop disposeOnUnmount
. You can verify that in the Inspector.
For the instancedMesh one. If you are using the code in your original message then you have destructured the parameter incorrectly. I think that may be the cause of the other one as well. Do a console.log or look at the properties of "rootMesh" parameter. The object being returned is actually a loaded model with animations, animation groups, etc: https://github.com/brianzinn/react-babylonjs/blob/master/packages/react-babylonjs/src/hooks/loaders/loadedModel.ts#L15
The code you likely want is not
<Model
onLoad={(root_mesh)=>{
root_mesh_ref.current = root_mesh
}}
</Model>
but instead
<Model
onModelLoaded={({rootMesh})=>{
root_mesh_ref.current = rootMesh
}}
</Model>
or
<Model
onModelLoaded={(loadedModel)=>{
root_mesh_ref.current = loadedModel.rootMesh
}}
</Model>
Your editor should be telling you all of this. If you are using TypeScript and you strongly type your useRef<T>
then you will know as well.
Long time no chat!
So I got it to work with
<>
<Suspense fallback={<box name="fallback" position={new Vector3(0, 0, 0)} />}>
<Model
ref={cavity_ref_temp}
rootUrl={ `./`}
sceneFilename={`cavity_blocks_compressed.glb?id=sample_instance_root3332`}
position={new Vector3(20, 20, 20)}
onModelLoaded={(rootMesh) => {
cavity_block_ref.current = rootMesh;
console.log(`setting cavity_block_ref:`);
setTimeout(() => {
setCavityBlockLoaded(true);
}, 2000);
}}
/>
</Suspense>
{cavityBlockLoaded && (
<>
{ <abstractMesh
fromInstance={cavity_block_ref.current.rootMesh}
position={new Vector3(1, 10, 1)}
name={`cavity_blocks_compressed2.glb?id=${31115}-model`}
/>
<abstractMesh
fromInstance={cavity_block_ref.current.rootMesh}
position={new Vector3(10, 1, 1)}
name={`cavity_blocks_compressed3.glb?id=${33212315}-model`}
/>
</>
)}
</>
However, only the last abstract mesh is visible, the original
I tried using
<instancedMesh
source={cavity_block_ref.current.rootMesh}
position={new Vector3(10, 1, 1)}
name={`cavity_blocks_compressed3.glb?id=${33212315}-model`}
/>
But that thew a bunch of console errors - any ideas what I need to tweak to create seperate instances of the initial model?
Yes. When you use fromInstance
the reconciler will not create a new mesh. So, it will just overwrite position and the last one received from the reconciler will be what you see. You probably want to use an instanced mesh. I'm going to publish a version now where the model has a forward ref to the root mesh. Then I think your example will work, if you switch abstract mesh to instance - using "source" prop.
@DenysAshikhin try on 3.1.26
that was just published. It will let you use <Model ref={...} />
as you have done.
Sounds good, let me give it a shot!
Updating fails to compile now:
My package.json:
It’s been renamed recently. Are you able to go to latest?
Sorry, which library to go latest?
@babylonjs.
Okay we are back up and running but I get the following stack: Am I supposed to use the red or green ref for instancedMesh?
I would say you would use cavity_ref_temp.current
for the instancedMesh. it will just be a transformnode though - depends on your model itself. i haven't tried instancing a hierarchy before.
😢
you have something like:
const cavity_ref_temp = useRef();
Can you change your timeout to:
setTimeout(() => {
console.log('cavite_ref_temp', cavity_ref_temp.current)
setCavityBlockLoaded(true);
}...);
You will hopefully see that the "rootMesh/root" is the ".current". You need to get the mesh you are after from the children of that Mesh. Babylon.js creates that root node and parents the model mesh(es) to it. Something seems to be off. Maybe we can make a code sandbox.
if you upload your glb here: https://sandbox.babylonjs.com/
then open the inspector - when you expand the "nodes" then you will see your meshes.
There is an official community request that will pave a road to make this easier to address: https://github.com/BabylonJS/Babylon.js/issues/14567
Closing out from inactivity. Thank-you for your contribution.
Hi,
I am currently creating copies/clones of the same model using:
Inside of
OnModelLoaded
I'm also grabbing the mesh reference:Then I am moving individual models with a
useBeforeRender
:Is it possible to achieve this using instances? The meshes are static, and only their individual location/rotation is updated as in the beforeRenderLoop. If it is, can someone guide the start? I have tried going over the doc for assetManager and mesh from instance but I'm not sure how to combine these things