Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Entity Color Options #1005

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
Open

Conversation

ewei2406
Copy link
Contributor

@ewei2406 ewei2406 commented Jan 2, 2025

[Revisal of #992]

Following the discussion, I implemented a widget to customize the colors of materials in each entity.
Screenshot 2025-01-01 at 7 11 17 PM

This PR depends on 3DStreet/3dstreet-assets-dist#37 for the new vertex colors in the specific entities in this screenshot. Otherwise, entities will have the material named atlas_colors as the only material, which is the UV map.

There is a button to add custom colors for an entity.
Screenshot 2025-01-01 at 9 47 19 PM

Once added, the user can pick which materials to modify. Multiple materials can be modified at the same time.
Screenshot 2025-01-01 at 6 08 43 PM
Screenshot 2025-01-01 at 9 47 59 PM

The data is serialized in the format: <material_name>:<overriden_color>;<material_name>:<overriden_color>;.... The component is not added by default - only when the customize button is clicked will it be created.

Copy link
Collaborator

@vincentfretin vincentfretin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This starts to be really great!

src/components/custom-colors.js Show resolved Hide resolved
// Save the original material color values
const newMaterials = getMaterials(entity.object3D);
newMaterials.forEach((material) => {
material.userData.origColor = material.color.clone();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be done in the aframe component, not here. There is probably an issue here, it will override material.userData.origColor with the current customized color if you select another car and back this car because the callback will be recreated.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That makes sense. I changed it to be initialized once whenever the component is added. Since this presents an issue if the model is changed, I will make it so that changing the model will remove the custom-colors component. This makes most sense, as most models will have unique materials

mapping[mat] = color;
});
return mapping;
}, [customColorData]);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can remove all this and use

const baseColorMapping = entity.getAttribute('custom-colors') ?? {}

after you redefined the custom-colors schema to use the custom parse/stringify.


const newColorsString = Object.entries(newColorMapping)
.map(([mat, color]) => `${mat}:${color}`)
.join(';');
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You don't need to serialize yourself, just give the object to execute.

} else {
entity.addEventListener('model-loaded', () => {
updateMaterials();
});
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can add {once: true} for this listener.

} else {
this.el.addEventListener('model-loaded', () => {
this.update();
});
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Properly unregister this model-loaded listener in remove.

  updateMaterials() {
    this.update():
  },
  init() {
    this.updateMaterials = this.updateMaterials.bind(this);
    if (this.el.getObject3D('mesh')) {
      this.update();
    } else {
      this.el.addEventListener('model-loaded', this.updateMaterials);
    }
  },
  remove() {
    this.el.removeEventListener('model-loaded', this.updateMaterials);
    ...
  }

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move the this.updateMaterials = this.updateMaterials.bind(this); at the beginning. Listening to model-loaded shouldn't be needed anymore if you listen on object3dset. object3dset is fired just before model-loaded https://github.com/aframevr/aframe/blob/cc43ea67f8170d8ca7e5bdcbaade031df103801e/src/components/gltf-model.js#L48-L49

@ewei2406
Copy link
Contributor Author

ewei2406 commented Jan 3, 2025

The new commits address the feedback and enable the coverage of the case when a user changes the model parameter of an entity that has the custom color component. Initially I was thinking to just remove the custom color component, but then I think it makes more sense to keep it if possible.

There was a problem with the timing of update with entities that use parts of a model (i.e. outdoor-dining). So I added the listener for object3dset, which covers the case.

The handling of the original colors is moved to the component instead

@ewei2406
Copy link
Contributor Author

ewei2406 commented Jan 3, 2025

The new PR for assets-dist here adds the named materials for the entities in vehicles tab

@kfarr
Copy link
Collaborator

kfarr commented Jan 20, 2025

hey @ewei2406

finally getting a chance to review this, it's really fun and useful, congrats!
image

here's some feedback

assets PR feedback (3DStreet/3dstreet-assets-dist#38)

  • I'm intrigued about the conversion to vertex colors for the assets -- does that mean there is no longer the same atlas embedded in each of those? do you have the original blender files for this vertex version or what is the method that you used for this conversion?
  • i noticed that about half of the modified glbs are roughly the same size, however 4 of them are quite a bit larger:
    waymo +169 KB (310%)
    new flyer bus +192 KB (300%)
    LRV +536 KB (400%)
    cable car +309 KB (320%)

for this pr:

  • i'm intrigued by this implementation that uses a custom widget with a component with a single value that is parsed, very neat
  • this could match the new component styling we just released and have a header (not just the enable/disable button) with items below, I can help with that
  • save / reload seems to work great
  • will this affect gltf > glb exports of the scene? (not critical, I can help test and diagnose that later)

next step:

  • how to get to asset size similar to originals after conversion to vertex colors? - Eddie
  • as a user I want to see a road with vehicles that have varying colors similar to the real world (new ticket: generate randomized vehicle colors when cloning) - KF
  • update ui to match new component styling - KF

@ewei2406
Copy link
Contributor Author

Hey Kieran, thanks for the feedback!

  • The atlas_colors uv map still exists and colors all the other vertices. Unfortunately I didn't save the blender files, but I can re-create quickly if you are interested in taking a look. My process was just to view all vertices on the UV map (I think its the 'coloring' tab), the just select all vertices in a certain area (i.e. guess which color is the body) and assign them to a new material.
  • Based on my research, the filesize should almost always increase since we have to add a new vertex_color field to all nodes, which I believe is 8bytes/nodes. But since each vertex uv map is already 8 bytes this shouldn't much more than a 100% increase in filesize - I think the most likely culprit is something to do with the Draco compression. I've got a bit of a busier week with my term starting, but I will take a look next weekend to see how to knock down those filesizes.

@kfarr
Copy link
Collaborator

kfarr commented Jan 21, 2025

@ewei2406 yes it is good to add original blender files here:
https://github.com/3DStreet/3dstreet-assets-source/

This is not an urgent item so please feel free to work on this as you have time

It sounds like we could convert the entirety of the 3d models to vertex colors instead of atlas / material? That'd potentially be a lot of work across all the 3d models, so not asking you to do this, just getting an idea of what might be a better long-term structure.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants