question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

[Question]: How to update a primitive's material?

See original GitHub issue

Hi, thank you for creating this awesome library!

I have a question which is both related to the implementation of this project and a bit of THREE…

I was wondering how I could change the material (on runtime) of a primitive object that uses a GLTF model. Passing <meshBasicMaterial> as a child for example does nothing, neither does passing material as a prop to my <primitive>.

I can’t make use of refs in my instance because I’m dynamically loading multiple models from an array… Like so:

  {buildings.map((building, i) => {
                const { position, rotation, scale } = buildingAttributeMap[i];
                return (
                  <primitive
                    key={i.toString()}
                    object={building}
                    position={position}
                    rotation={rotation}
                    scale={scale}
                    material={null}
                  />
                );
              })}

I hope this makes sense, if anything is unclear, please let me know.

Thanks in advance!

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Comments:6 (2 by maintainers)

github_iconTop GitHub Comments

1reaction
drcmdacommented, Jun 11, 2019

gltf loads a full scene with nested meshes and materials all readymade. That’s the downside with imperative stuff, changing things always means going through ugly traversals.

<primitive object={building} material={...} /> won’t do anything if the referenced object (in this case building) doesn’t have a material property. Generally in threejs meshes and lines have the material property, groups and object3d’s don’t have it.

If you know the structure you could use object piercing. Example: https://codesandbox.io/s/reactthreefiber-suspense-gltf-loader-vk48w

<primitive object={scene} children-0-children-1-material-color="red" />

But that makes for a very implicit contract between your code and the gltf scene.

0reactions
VityaSchelcommented, Dec 13, 2021

Is there a way to use object piercing with material names instead of children indexes?

I made this simple function which converts material properties into props:

export const applyMaterial = (scene, materials) => {
  const props = {}
  for(let [materialName, value] of Object.entries(materials)) {
    const recursiveSearch = obj => {
      for(let childIndex in obj.children) {
        const child = obj.children[childIndex]

        if(child.children.length) {
          const searchResult = recursiveSearch(child)
          if(searchResult) return `children-${childIndex}-${searchResult}`
          else continue
        } else {
          if(child?.material?.name === materialName) {
            return `children-${childIndex}-material`
          }
        }
      }
    }

    const template = recursiveSearch(scene)
    // const properties = flattenObject(value) Breaks if value is used as object
    for(let [propertyName, propertyValue] of Object.entries(value)){
      props[`${template}-${propertyName}`] = propertyValue
    }
  }
  return props
}

It must be used on primitive like this:

    <primitive>
        {...applyMaterial(card.scene, {
          'cube': { roughness: 1, 'color-r': cubeColor, 'color-g': cubeColor, 'color-b': cubeColor }
        })}
    </primitive>

And it works with springs

Haven’t tested it with nested objects tho but it should work 😅

Read more comments on GitHub >

github_iconTop Results From Across the Web

[Question]: How to update a primitive's material? #112 - GitHub
I was wondering how I could change the material (on runtime) of a primitive object that uses a GLTF model. Passing <meshBasicMaterial> as...
Read more >
how to update polygon material in 1.17? - Cesium Community
In 1.16, we would update a polygon's material just by changing the material and calling configurePolygonHierarchy: polygon.material = Cesium ...
Read more >
How to scale primitives independently from material?
The only way I've found so far, is to duplicate the material, and use the X and Y stretching panel (into the scale...
Read more >
Material Custom Primitive Data Not Updating Each Frame In ...
In standalone, the materials reflect the custom primitive data being passed in per mesh only after I've added a new instance to the...
Read more >
What are 3D Primitive materials? - Clip Studio Official Support
2. Select Primitive, then drag and drop the material you want onto the canvas. 1.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found