How can I add the texture to model using react-babylonjs npm?

This is my code block . Thank you

 <Suspense fallback={<box name="fallback" />}>
            <Model
              rootUrl={`https://raw.githubusercontent.com/ml-bhanuprakash/babylonjs/main/test_3/`}
              sceneFilename={`blouse_03.glb`}
              scaleToDimension={0}
              // morphTargetManager={ MorphTargetManager. }
              // scaling={new Vector3(1,1,1)}

              onModelLoaded={(model) => {
                onModelLoaded(model);
              
              }}
              name={""}
            ></Model>

const onModelLoaded = (model: any) => {
console.log(model);
let mesh = model.meshes[1];
};

Hello @Chaitanya_Yanamala , welcome to the Babylon forum!

Is your question react specific or just how to add a texture to a mesh in general? This can be done by assigning a texture to the mesh.material.diffuseTexture.

To learn more about what you can do with the materials please check out our documentation:
Introduction To Materials | Babylon.js Documentation (babylonjs.com)

1 Like

Thank you for your reply. I will try once diffuseTexture. And the question is react specific.

This is onModelLoaded function . This is working fine. Thank you for the support.

const onModelLoaded = (model: any) => {
console.log(model);
let mesh = model.meshes[1];
mesh.actionManager = new ActionManager(mesh._scene);

console.log(model.meshes[1].material._albedoTexture);

mesh.actionManager = new ActionManager(mesh._scene);

mesh.material.albedoTexture =  new Texture("https://c.static-nike.com/a/images/w_1920,c_limit/mdbgldn6yg1gg88jomci/image.jpg")

mesh.material.diffuseTexture =  new Color4(0.02, 0.022, 0.02, 1)

};

1 Like

Lets add @brianzinn the mind behind the react-babylonjs package

1 Like

Sorry for the late reply - if you want the texture to pre-load you could try something slightly more declarative. That can save you a bit of a glitch loading the texture as it will likely probably load before the model.

const MyComponent = () => {
  const textureRef = useRef<Texture | null>(null);

  const onModelLoaded = (model: ILoadedModel) => {
    ...
    model.meshes[1].albedoTexture = textureRef.current;
  }

  return (
    <>
      <Suspense ...><Model .../></Suspense>
      <texture ref={textureRef} ... />
    </>
  )
}

The nice thing about that is that texture props will still flow to the texture, so you can change them dynamically at runtime, since the react-babylonjs reconciler maintains a ref. In this example, you can change the roughness of the textures by clicking a button, if you wanted access to the textures from state.
Textures - PBR set roughness ⋅ Storybook (brianzinn.github.io)

1 Like

Thank you @brianzinn for your reply. I will try this way also.

Hey @brianzinn! First of all thanks for your work here helping everyone, lots of useful information!
I am starting just now with React-Babylon, I managed to load a sneaker mesh and change its material texture as per your suggestion, that’s great.
I was wondering how would one go by creating changing the texture dynamically with a button, as you said in this message?

Thanks so much!

1 Like

The easiest way is to trick the reconciler with a key. ie:

import { useState } from 'react';

const ReflectiveSphere = ({position, reflectionTextureUrl}) => {

  return (
    <sphere
          name="sphere2"
          position={position}
          segments={32}
          diameter={3}
        >
          <standardMaterial
            name="material2"
            specularPower={32}
            diffuseColor={Color3.Black()}
            emissiveColor={new Color3(0.5, 0.5, 0.5)}
          >
            <cubeTexture
              key={reflectionTextureUrl}
              assignTo="reflectionTexture"
              rootUrl={reflectionTextureUrl}
            />
          </standardMaterial>
        </sphere>
  )
}
)

That would, for example, create a new cube texture and assign it to the standardMaterial.reflectionTexture. Now to get a button to change the cube texture probably memoize the component and whenever you send through a different reflectionTextureUrl prop (or position) it will be reflected on the sphere and texture. Does that help? It’s a bit of a contrived example without a button, but I would recommend a state management library like zustand.

If you are using some ecommerce settings available in models then it could be a different solution as it’s already available I believe. You could also use a useEffect for when the url changes in dependency array to change when it’s loaded - that will increase time without a material, since the original material is disposed(). You can use also fromInstance like I do here if you want to manage your own lifetime of the assets:
react-babylonjs/image-texture.stories.js at master · brianzinn/react-babylonjs (github.com)

There is an opt-in mechanism to disposeOnUmount with those. Unfortunately there are no docs, so it’s really hard to figure all those things out. I have some new docs that are super good, but not 100% ready…

Let me know if that solves it for you @PabloCodeglia - otherwise we can look at a solution. Lastly if you are using Models or useSceneLoader hook then you can directly assign those to a mesh with fromInstance. That’s how the <Model ../> component works as it is a little wrapper:
react-babylonjs/Model.tsx at master · brianzinn/react-babylonjs (github.com)

Cheers - really good question BTW.

1 Like

@brianzinn Nice!!! Lots to take in and, honestly, not sure I understand all of it :sweat_smile: but I will do my research and try to make sense of it all! Thanks for all the help!

It’s not really easy to grasp - but consider that constructor arguments are only used once. So, arguments like ‘url’ for textures do not cause the component to be disposed. I could write it so that props for constructor arguments recreate objects, but I don’t know what would be gained - so, unfortunately right now it requires a bit of knowledge about babylon constructor vs. property props. (property props are continuously updated even if they match a constructor name).