Obi Official Forum
Help import and export blueprint property values in script - Printable Version

+- Obi Official Forum (https://obi.virtualmethodstudio.com/forum)
+-- Forum: Obi Users Category (https://obi.virtualmethodstudio.com/forum/forum-1.html)
+--- Forum: Obi Cloth (https://obi.virtualmethodstudio.com/forum/forum-2.html)
+--- Thread: Help import and export blueprint property values in script (/thread-3094.html)



import and export blueprint property values in script - joe smith - 13-09-2021

Hi there, 

As described in the title, i'd like to import and export blueprint property using an image.
For example, i'd like to 

  1. export initial skin radius values as an image, 
  2. process the image in other tools, and 
  3. import back it in unity in script.

the manual import/export instruction works fine with GUI.
But we have a large number of cloth models, and i don't know how to use this in a batch script. 

In short, i'd like to use it as follows and wonder if it is possible:
Code:
// create the blueprint: (ObiClothBlueprint, ObiTearableClothBlueprint, ObiSkinnedClothBlueprint)
var blueprint = ScriptableObject.CreateInstance<ObiClothBlueprint>();

// set the input mesh:
blueprint.inputMesh = yourMesh;

// generate the blueprint:
yield return StartCoroutine(blueprint.Generate());

// import property values, e.g.
// blueprint.import(property="skinRadius", file="xxx.png", min=0, max=10) ??


Would you please help me how to do this properly?


RE: import and export blueprint property values in script - josemendez - 13-09-2021

Hi there,

The included functions to read/write properties from/to textures can only be used in-editor, since they rely on writing/reading assets directly which cannot be done at runtime. If you're writing an editor script, you will find these functions in ObiMeshBasedActorBlueprintEditor:

Code:
ReadParticlePropertyFromTexture(Texture2D source, Action<int, Color> onReadProperty);
WriteParticlePropertyToTexture(string path, int width, int height, int padding);

Reading takes a texture as input, and an action that gets called for each particle in the actor. The two parameters passed to this callback are the particle index and the texel Color value read from the texture.

Note it is trivial to write your own method that reads an existing texture at runtime, outside of the editor. All you need to do is iterate over all vertices in the mesh, read the texel value at the vertex uv coordinate, and then map the value to any property/range you need. For instance:

Code:
void Read(Texture2D input, ObiMeshBasedActorBlueprint blueprint)
{
            Vector2[] uvs = blueprint.inputMesh.uv;

            // Iterate over all vertices in the mesh reading back colors from the texture:
            for (int i = 0; i <  blueprint.inputMesh.vertexCount; ++i)
            {

                    int particleIndex = blueprint.topology.rawToWelded[i];
                    var color = input.GetPixelBilinear(uvs[i].x, uvs[i].y));

                   // map the color to any property you want:
                   blueprint.principalRadii[particleIndex] = color.r  * 10;
            }
}



RE: import and export blueprint property values in script - joe smith - 13-09-2021

josemendez

Note it is trivial to write your own method that reads an existing texture at runtime, outside of the editor. All you need to do is iterate over all vertices in the mesh, read the texel value at the vertex uv coordinate, and then map the value to any property/range you need. For instance:

Code:
void Read(Texture2D input, ObiMeshBasedActorBlueprint blueprint)
{
            Vector2[] uvs = blueprint.inputMesh.uv;

            // Iterate over all vertices in the mesh reading back colors from the texture:
            for (int i = 0; i <  blueprint.inputMesh.vertexCount; ++i)
            {

                    int particleIndex = blueprint.topology.rawToWelded[i];
                    var color = input.GetPixelBilinear(uvs[i].x, uvs[i].y));

                   // map the color to any property you want:
                   blueprint.principalRadii[particleIndex] = color.r  * 10;
            }
}

Thanks @josemendez. that is what i was looking for 
It seems i can directly write particle parameter values on a texture map. I'll test the idea soon.
 
In the meantime, can you please help me to understand a few more things about the code?
  • Q1> does it mean that ObiCloth will generate the same number of particles as inputMesh.vertexCount? (I thought it would create a sparse set of particles by approximating the input mesh)
  • Q2> what is rawToWelded? I can find the name in the class reference but cannot find what it is.
Probably fundamental concepts but I cannot find any useful information from the class reference Triste

Many thanks!


RE: import and export blueprint property values in script - josemendez - 14-09-2021

(13-09-2021, 10:15 PM)joe smith Wrote: [*]Q1> does it mean that ObiCloth will generate the same number of particles as inputMesh.vertexCount? (I thought it would create a sparse set of particles by approximating the input mesh)
[*]Q2> what is rawToWelded? I can find the name in the class reference but cannot find what it is.
[/list]Probably fundamental concepts but I cannot find any useful information from the class reference Triste

Hi!

Both questions revolve around the same basic concept: welded or "shared" vertices.

You know meshes are basically a bunch of vertices and a list of triangles (triads of vertex indices). Each vertex has a position, a normal, a tangent, color, a  texture coordinate, etc. However, you cannot have 2 normals per vertex, or 3 colors, or 2 texture coordinates. So what do you do when you must have a single vertex with different texture coordinates (a texture seam) or different normals?

Think of a simple cube: it has 8 vertices right?

Nope, it has 24: each vertex is shared by 3 faces, and each face has a different normal. Since you can't have a single vertex with 3 normals, at each corner of the cube you must have 3 vertices with the same position and a normal of their own each. This is a fundamental concept in mesh "anatomy".

Back to Obi cloth: when generating particles, it makes no sense to create one particle per vertex: many particles would end up overlapping, since there's multiple vertices with the exact same position (but different normals, texcoords, colors, etc). So vertices with the same position are welded into a single vertex, and a particle generated out of it.

This is where the rawToWelded array comes into play: it maps the index of a raw vertex to the index of a welded vertex / particle. So all this line does:

Code:
int particleIndex = blueprint.topology.rawToWelded[i];

Is get the particle index that corresponds to raw vertex "i".

let me know if you need further help. cheers!