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

feat(subset): add support for material slot names #229

Draft
wants to merge 6 commits into
base: develop
Choose a base branch
from

Conversation

NMC-TBone
Copy link
Contributor

A working example for setting new materialSlotName attribute in shapes subsets.

The main challenge is ensuring that the materialSlotName is unique per material, per mesh. Since a mesh can contain multiple materials, each material within a mesh must have the possibility to have its own unique materialSlotName.

@NMC-TBone
Copy link
Contributor Author

NMC-TBone commented Dec 13, 2024

from private chat:

New attribute called "materialSlotName" Is a way for the game to identify materials within e.g. color configurations and stuff.

    <baseColorConfigurations useDefaultColors="true" defaultColorMaterialTemplateName="metalPainted">
        <baseColorConfiguration color="SHARED_REDCRIMSON"/>

        <material materialSlotName="262MonsterV_metalPainted_mat"/>
    </baseColorConfigurations>
<Materials>
  <Material name="Material" materialId="1" diffuseColor="0.800000 0.800000 0.800000 1.000000" specularColor="0.500000 0.500000 0.000000"/>
  <Material name="Material2" materialId="2" diffuseColor="0.800000 0.800000 0.800000 1.000000" specularColor="0.500000 0.500000 0.000000"/>
</Materials>
<Shapes>
  <IndexedTriangleSet name="Cube.003" shapeId="1">
    <Subsets count="2">
      <Subset firstIndex="0" firstVertex="0" numIndices="6" numVertices="4" materialSlotName="onObjectCube"/>
      <Subset firstIndex="0" firstVertex="0" numIndices="6" numVertices="4" materialSlotName="onObjectCube_Second"/>
    </Subsets>
  </IndexedTriangleSet>
  <IndexedTriangleSet name="Cube.001" shapeId="2">
    <Subsets count="1">
      <Subset firstIndex="0" firstVertex="0" numIndices="6" numVertices="4" materialSlotName="onObjectCube.001"/>
    </Subsets>
  </IndexedTriangleSet>
</Shapes>
<Dynamics/>
<Scene>
  <Shape name="Cube" nodeId="1" materialIds="1 2" shapeId="1"/>
  <Shape name="Cube.001" nodeId="2" materialIds="1" shapeId="2" translation="-3.20797 3.96826 2.37168"/>
</Scene>

The complicated part with materialSlotName is:

  • Its stored within the Shape subset
  • This means separate shapes/meshes can share the same material, but have unique materialSlotName, since its stored inside shape subset.
  • If we store it in bpy.types.Material, it will add the same materialSlotName for all the shapes that have the same material. That will not work.
  • Storing it directly on bpy.types.Mesh as StringProp will work as a simple solution, but if a mesh have multiple materials, all subsets on the shape will end up with the same materialSlotName and that will not work

So I guess the only solution for this will be to have a collection property on bpy.types.Mesh and store materialSlotName and e.g. material index inside that property? But how that should be updated/added into the UI I am not really sure about 🙈

materialSlotName.zip

@LKAMinco
Copy link
Contributor

It can be done like the shader picker. The main problem is when u want to have it 100% responsive, u will need to detect all the time UI is rendered all materials on mesh, what can cost the performance.

@StjerneIdioten
Copy link
Owner

So just to make sure I understand the new setup correctly:

  • Each subset now has a materialSlotName
  • The configurations in the vehicle xml will use the materialSlotName to select the correct subset to modify the material of
  • The Shape node still links materials to subsets by the materialIds and the definition order of the subsets

@NMC-TBone
Copy link
Contributor Author

So just to make sure I understand the new setup correctly:

  • Each subset now has a materialSlotName
  • The configurations in the vehicle xml will use the materialSlotName to select the correct subset to modify the material of
  • The Shape node still links materials to subsets by the materialIds and the definition order of the subsets

Sounds correct yea

@StjerneIdioten
Copy link
Owner

StjerneIdioten commented Dec 13, 2024

In that case, wouldn't it be possible to just generate a unique ID per slot based on the mesh name?

<IndexedTriangleSet name="Cube" shapeId="1">
    <Subsets count="2">
      <Subset firstIndex="0" firstVertex="0" numIndices="6" numVertices="4" materialSlotName="Cube0"/>
      <Subset firstIndex="0" firstVertex="0" numIndices="6" numVertices="4" materialSlotName="Cube1"/>
    </Subsets>
  </IndexedTriangleSet>

I don't know if each IndexedTriangleSet needs a unique name in the .i3d, but they do in Blender and I don't think we added anything to override that part.

If that is annoying then we could keep a list of "Materialslot Index -> Material Slot Name" mappings per Blender mesh object. To avoid having to keep in sync with the material list of the object. We could default to using the slot index as the name tagged onto the mesh name if a name isn't defined in the list for that index.

image

image

<IndexedTriangleSet name="Cube" shapeId="1">
    <Subsets count="3">
      <Subset firstIndex="0" firstVertex="0" numIndices="6" numVertices="4" materialSlotName="UniqueName1"/>
      <Subset firstIndex="6" firstVertex="0" numIndices="12" numVertices="4" materialSlotName="UniqueName2"/>
      <Subset firstIndex="12" firstVertex="0" numIndices="18" numVertices="4" materialSlotName="CubeSlot2"/>
    </Subsets>
  </IndexedTriangleSet>

Or if it is very important to guarantee uniqueness, we could say that it is material slot prefixes instead and have something like this and prefix the mesh name always

<IndexedTriangleSet name="Cube" shapeId="1">
    <Subsets count="3">
      <Subset firstIndex="0" firstVertex="0" numIndices="6" numVertices="4" materialSlotName="Cube_UniqueName1"/>
      <Subset firstIndex="6" firstVertex="0" numIndices="12" numVertices="4" materialSlotName="Cube_UniqueName2"/>
      <Subset firstIndex="12" firstVertex="0" numIndices="18" numVertices="4" materialSlotName="Cube_Slot2"/>
    </Subsets>
  </IndexedTriangleSet>

I think the most important thing is that it is consistent such that whatever materialSlotName used in the vehicle xml doesn't have to change unless you rearrange things yourself and even better if you can predict the name based on your hierarchy.

The one little caveat I can see to this is we would have to see if this is as easy for merge group, but I guess technically even the order for those is consistent and predictable. It's just not easily changeable, thus being able to set the suffix name yourself on the Blend mesh object would make it a lot easier as it would just become "MergeMeshName_YourChosenSuffix" for the material name.

@NMC-TBone
Copy link
Contributor Author

NMC-TBone commented Dec 13, 2024

IndexedTriangleSet does not need unique names in .i3d because they are referenced directly using shapeId. Yea generating the materialSlotName based on the mesh name is a possibility for sure.

However, I think its important to allow users somewhat control over the final materialSlotName .

Some example of names Giants have used for their materialSlotName:
baseColorConfigurations from in game Volvo FH16

    <baseColorConfigurations useDefaultColors="true" defaultColorMaterialTemplateName="calibratedMetallicPaint">
        <baseColorConfiguration color="VOLVO_GREEN1" isSelectable="false"/> <!-- Only for FH Electric version -->
        <baseColorConfiguration color="VOLVO_PURPLE1"/>
        <baseColorConfiguration color="VOLVO_RED1"/>
        <baseColorConfiguration color="VOLVO_BM_GREEN1"/>
        <baseColorConfiguration color="VOLVO_YELLOW1"/>
        <baseColorConfiguration color="VOLVO_GREY1"/>

        <material materialSlotName="fh16_main_color_mat"/>
        <material materialSlotName="fhElectric_main_color_mat"/>
        <material materialSlotName="fhElectric_additionalParts01_color_mat"/>
        <material materialSlotName="fhElectric_additionalParts02_color_mat"/>
    </baseColorConfigurations>

designConfigurations from in game `Sennebogen 340 G

    <designConfigurations>
        <designConfiguration name="Sennebogen 340 G">
            <objectChange node="config_sennebogenDecals" visibilityActive="true" visibilityInactive="false"/>
            <objectChange node="config_sennebogenArmDecals" visibilityActive="true" visibilityInactive="false"/>
            <objectChange node="config_sennebogenCabinDecals" visibilityActive="true" visibilityInactive="false"/>
            <objectChange node="config_sennebogenCabinDoorDecals" visibilityActive="true" visibilityInactive="false"/>
            <material materialSlotName="armColorGrey_mat" materialTemplateName="FENDT_GREY2" />
            <material materialSlotName="cabinDecal_mat" materialTemplateName="SENNEBOGEN_GREEN1" />
        </designConfiguration>

        <designConfiguration name="Fendt Cargo T 740" isSelectable="false">
            <objectChange node="config_fendtDecals" visibilityActive="true" visibilityInactive="false"/>
            <objectChange node="config_fendtCabinDecals" visibilityActive="true" visibilityInactive="false"/>
            <objectChange node="config_fendtSeatDecals" visibilityActive="true" visibilityInactive="false"/>
            <objectChange node="config_fendtArmDecals" visibilityActive="true" visibilityInactive="false"/>
            <material materialSlotName="chassiColorGreenGlossy_mat" materialTemplateName="FENDT_NEWGREEN1" materialTemplateUseColorOnly="true"/>
            <material materialSlotName="chassiColorGreen_mat" materialTemplateName="FENDT_NEWGREEN1" />
            <material materialSlotName="chassiColorGrey_mat" materialTemplateName="FENDT_GREY2" />
            <material materialSlotName="chassiColorGrey2_mat" materialTemplateName="FENDT_GREY2" />
            <material materialSlotName="chassisColorGreyCastIron_mat" materialTemplateName="FENDT_GREY2" materialTemplateUseColorOnly="true"/>
            <material materialSlotName="cabinWhite_mat" materialTemplateName="FENDT_NEWGREEN1" />
            <material materialSlotName="armColorGrey_mat" materialTemplateName="FENDT_NEWGREEN1" />
            <material materialSlotName="cabinDecal_mat" materialTemplateName="FENDT_NEWGREEN1" />
        </designConfiguration>
    </designConfigurations>

As long as the final materialSlotName is clearly visualized in Blender, any consistent and predictable solution should work imo.

Should also try to avoid including the attribute in the .i3d for parts that will not actually use it.

@StjerneIdioten
Copy link
Owner

However, I think its important to allow users somewhat control over the final materialSlotName .

And they will have full control with a list of slot names they can add to along with the mesh as a prefix. Both of those can be used configured.

Some example of names Giants have used for their materialSlotName: baseColorConfigurations from in game Volvo FH16...

So no consistency between models 😂

Should also try to avoid including the attribute in the .i3d for parts that will not actually use it.

Of course

@NMC-TBone
Copy link
Contributor Author

NMC-TBone commented Dec 13, 2024

However, I think its important to allow users somewhat control over the final materialSlotName .

And they will have full control with a list of slot names they can add to along with the mesh as a prefix. Both of those can be used configured.

Sounds good! 👍

Some example of names Giants have used for their materialSlotName: baseColorConfigurations from in game Volvo FH16...

So no consistency between models 😂

Nope 😅😂

Should also try to avoid including the attribute in the .i3d for parts that will not actually use it.

Of course

👍

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