Mesh color mapping - sample project

mcm_github
(Click to play the demo on itch)

This sample project demonstrates a method for mapping vertex colors from mesh for real-time manipulation. During gameplay you can recolor mapped parts of the mesh.

In defold we can use 3d assets that have vertex color data from export and display them in game and that is great. However one question that comes to mind is how do we change these colors in real-time? Some games have gear coloring mechanics, for example a player can use dye to customize the colors of their gear. Another example would be a charging weapon that flashes and changes colors while being charged up. In this case we can find the mesh component very useful for this purpose.

How can it done? Using the mesh component api we can get the mesh then the mesh buffer as a resource and last get the color stream. With some basic 3d concepts we can loop through the stream and map out different colors and index the data. Lets go over these basic 3d concepts.

tri_face

3d meshes are made up of triangles. When we export our mesh buffers with vertex color streams they can read like so: {"name":"color","type":"float32","count":4,"data":[0.0,0.0,0.0,1.0 etc..]} float32 & count 4 meaning we store 4 float32’s per vertex. So since we know that every 4 values in the color stream is equal to one vertex then every 12 values is equal to one triangle face. With this knowledge we can assume that when doing a for loop through the color stream we can check 4 values of color equal to one vertex and skip 12 to the next face. Example for i = 1, count, 12 do. We store every new color or if we match a color we store the color stream index with the matched color that way we can use it later to know exactly what triangle faces in the mesh to color. This is the gist of how it works!

The sample project has a module with functions for mapping data

  • M.map_vertex_colors(mesh_url): Takes in mesh url. Maps indexes of all triangle faces and their vertex color values with matching colors

  • M.color_on_mesh(mesh_url, mapped_id, color): Takes in mesh url, map id(mapped index), vector 4. Changes mesh mapped color to new color

  • M.mesh_info(mesh_url): Takes in mesh url. Prints out data of mapped mesh

  • M.remove_mesh(mesh_url): Takes in mesh url. Removes mesh data and buffer stored in module tables

Notes: I added a remove_mesh function to highlight the idea that the data should be removable. For a game that is in production it may be implemented for optimization and clean up during the playthrough. For example the player is in later stages of gameplay and certain mesh are no longer available during the rest of the game. Speaking of optimizations this sample could be optimized in several ways, one thing is that the stored alpha values for all colors are not used they are always a value of 1.0 and we could find ways to not store those values. One thing to think about if you are wanting to create a similar mechanic in your game would be to separate the data from the module and store it in a way that you can save and load the data after playing and exiting your game.

Keep in mind mapping vertex color streams can be used for other creative mechanics, more than just coloring. For example you could alter the shape or scale of parts of a mesh etc. If you come up with a cool mechanic please share it with us!

Sample Project:

Cheers!~ :metal:

16 Likes

This is amazing! :heart_eyes:

2 Likes

Looks amazing. I had a couple of issues with it (commit b9c12af4129173719fd58afde1a631fa061ccd88).

  • The png’s in /assets/textures are corrupted.
  • The texture references under logic/nodes/UI are all red ‘does not exist in the scene’.

Defold build errors state ‘no matching image reader’ for all the png’s (also gimp can’t load them).
This is with Defold 1.9.4 on Ubuntu 22. Possibly needs a change set pushing, or I have got something wrong.

3 Likes

I committed to the repository with lf line endings and corrupted the .png images. I believe the issue has been fixed. Please let me know if you still have issues. Thank you for letting me know.

3 Likes

Great thanks, works now.

3 Likes