brianzinn / react-babylonjs

React for Babylon 3D engine
https://brianzinn.github.io/react-babylonjs/
818 stars 105 forks source link

using a model multiple times #144

Closed rikkertkoppes closed 3 years ago

rikkertkoppes commented 3 years ago

I am trying to display the same model multiple times. What I probably mean is multiple instances of the same model as the geometry and textures are all the same.

my initial approach was just using <Model> multiple times (as a component I can reuse)

const ConeView = ({ name, cone }: ConeProps) => {
    let { x, y } = cone.get("position");
    return (
        <transformNode name={name} position={new Vector3(y, 0, x)}>
            <Suspense fallback={null}>
                <Model
                    name={`${name}_model`}
                    rootUrl={"/models/"}
                    sceneFilename={"cone.gltf"}
                />
            </Suspense>
        </transformNode>
    );
};

however, the object is displayed only 1 time. I am not sure why actually, so any insights here are welcome

Next, 1 tried using useSceneLoader with instancedMesh:

const ConesViewPres = () => {
    let cone = useSceneLoader("/models/", "cone.gltf");
    console.log(cone, cone.status);
    let mesh = cone.meshes[1];

    return (
        <>
            <instancedMesh source={mesh} name={`cone1`} />
            <instancedMesh
                source={mesh}
                position={new Vector3(1, 0.25, 0)}
                name={`cone2`}
            />
        </>
    );
};

the funny thing is, when I use cone.meshes[0], as I originally expected should work, I get the same behaviour as before (1 cone), when using cone.meshes[1], I get 2 cones. There is only one mesh in the gltf file, however, inspecting the cone object revealed 2 objects in that array. I am not sure why.

using useSceneLoader however, does seem to render my ConesView component very often, even though nothing is changed inside the component (thing do change in a parent component, but this one is wrapped in a Redux connect(), so should only repaint when attributes change, or, obviously, when reacting to hooks). I'd also like to know why the hook keeps repainting the component.

Bottom line is: what is the best way to use multiple instances of the same model?

brianzinn commented 3 years ago

Yes, that is a good question. It has popped up before and it actually deserves a "recipe" page on it's own. Here is an example from another issue that is similar and explains the mechanism and why it is not working for you. https://github.com/brianzinn/react-babylonjs/issues/129

For a way to declare instances of existing meshes there are examples linked from here: https://github.com/brianzinn/react-babylonjs/issues/104

If that doesn't provide a solution then we can look into a way to influence the caching using by Suspense, which is the root cause of the issue. I would actually be happy to work with you on a better solution and storybook example, because in the game that I built what I did was loaded the mesh and then created instances from that first mesh - instanced meshes have better performance.

brianzinn commented 3 years ago

closing from inactivity. hope those links helped you find a solution. please re-open if you have more questions or require a better solution.