animate1978 / MB-Lab

MB-Lab is a character creation tool for Blender 4.0 and above, based off ManuelBastioniLAB
Other
1.83k stars 315 forks source link

Morphs creation (Copy/Move/Delete/Rename/Backup morphs tool done) #226

Open TetoTheSquirrelFox opened 4 years ago

TetoTheSquirrelFox commented 4 years ago

So, I try to help by making tools to create like morphs (or muscle if I can figure how it works).

But I had to answer few questions first :

So what I think about that:

You can see the content in characters_config here: "f_no01": { "description": "Generate a base female character for creating morphs", "template_model": "MBLab_human_female", "name": "f_no01", "label": "Base female (F_NO01) (AGPL3)", ... "texture_sclera_mask" : "sclera_mask.png", "morphs_extra_file": "", "shared_morphs_file": "", "shared_morphs_extra_file": "", "bounding_boxes_file": "human_female_bbox.json", ... "vertexgroup_base_file": "human_female_vgroups_base.json", "vertexgroup_muscle_file": "human_female_vgroups_muscles.json" }

Problem is that some morphs could be very specific to a race or a phenotype, and could not work properly in all models for a reason. So I decided that user could use the model he wants, and create his own morphs while other morphs are already used. To assure that, I put the “morphs editor” in the Pre-Finalized State session (gui_status == "ACTIVE_SESSION") and put it between “random generator” and “measures”. So, for the user who chooses “F_NO01” he can create, and for the others he can use other morphs as well.

So, as MB_Lab is not designed to create bodies from scratch, but more to use what it is available, I tried to be as simple as possible, while let the user to have the most useful tool to create new morphs.

So now here are the problems I’m facing :

At first, the tool would have looked like this (on the panel):

But, first I wanted to have my own models, copies of the ones used by the engine, but after a while I started to think that it was not good. The engine is complex, and I should keep a coherence with it. The model the user is working on is linked to the engine, so let’s keep it that way. And the engine has already many useful tools like reset, loading, saving… So, if the user wants making morphs from base model, no problem, he can use the “reset character” button. If he wants to create while character already has morphs applied, he can use ‘import/export character”.

So now the tool looks like this :

The workflow would look like this :

I’m working on it now, and if you agree, I’d like to make a morph.py dedicated for this, so the changes in other .py files would be minimal. I’d like to talk about the work in progress here too.

animate1978 commented 4 years ago

Quite impressive! I will have to read this over again as I only read through it once but so far what I see I like.

Of course making a new morph Python script would be ideal.

We can make this a project for the next version perhaps?

TetoTheSquirrelFox commented 4 years ago

Thanks. ^^

About a new project, why not, but I'd like to be sure that what I'm doing goes somewhere. For now I'll change the existing python files to "prepare" the creation tools, and will post the changes here.

TetoTheSquirrelFox commented 4 years ago

image Now, first thing to do is to store a copy of the body (all vertices to be more specific) because after sculpting the morph, I need to compare with a base, and as the actual body has changed, I need an untouched body to compare with.

But I can't write body_as_a_base = actual_body, I suppose, and I must something like body_as_a_base = actual_body.duplicate() and make a real copy, not an instance. I'll on this tomorrow. And I think that will help me for comparing 2 body objects.

By the way, about the classes I'm modifying : the changed code is always between

Teto

and

End Teto

So when it will be done, I will be able to send the files to you and it will be easy (I guess) to change the files in master. Please tell me if I'm wrong.

Noizirom commented 4 years ago

I'm not sure, but you might want to make a bmesh copy to sculpt, then bake it back to the original mesh. I do think that you can obtain the un_modified coordinates the same way you access the "current" coordinates, but I've never actually used those.

On Mon, Jan 13, 2020, 3:43 PM TetoTheSquirrelFox notifications@github.com wrote:

[image: image] https://user-images.githubusercontent.com/59537161/72289918-6cdc1b00-364c-11ea-80cd-6db8925675e0.png Now, first thing to do is to store a copy of the body (all vertices to be more specific) because after sculpting the morph, I need to compare with a base, and as the actual body has changed, I need an untouched body to compare with.

But I can't write body_as_a_base = actual_body, I suppose, and I must something like body_as_a_base = actual_body.duplicate() and make a real copy, not an instance. I'll on this tomorrow. And I think that will help me for comparing 2 body objects.

By the way, about the classes I'm modifying : the changed code is always between

Teto

and

End Teto

So when it will be done, I will be able to send the files to you and it will be easy (I guess) to change the files in master. Please tell me if I'm wrong.

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/animate1978/MB-Lab/issues/226?email_source=notifications&email_token=AKYHC3XRPNKH7TUN4GVU4MTQ5TG63A5CNFSM4KFX5YB2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEI2G24Q#issuecomment-573861234, or unsubscribe https://github.com/notifications/unsubscribe-auth/AKYHC3UFGXVKB2TBDEANNQLQ5TG63ANCNFSM4KFX5YBQ .

TetoTheSquirrelFox commented 4 years ago

No no, it's waaaaay simpler than that. ^^ Actually I want to make a copy of the vertices of the shown model. And a python program already exists for this (it writes in a file, I just want to make a special object that stores the vertices). After that, user does his thing with Blender sculpt tools (without touching the number/name/id of vertices of course). And at the end the tool checks just the differences between the base and the sculpted, then write them in a json file in order to be a regular morph.

So no, I don't "touch" anything in the model, I just check the differences between 2 states of a same model that is entirely handled by the engine (which is complex, like, really complex).

Noizirom commented 4 years ago

A file called co_to_js.py will put vertices of a selected object into a .json file. https://github.com/Noizirom/Blender-Python-Tool

On Wed, Jan 15, 2020, 2:26 PM TetoTheSquirrelFox notifications@github.com wrote:

No no, it's waaaaay simpler than that. ^^ Actually I want to make a copy of the vertices of the shown model. And a python program already exists for this (it writes in a file, I just want to make a special object that stores the vertices). After that, user does his thing with Blender sculpt tools (without touching the number/name/id of vertices of course). And at the end the tool checks just the differences between the base and the sculpted, then write them in a json file in order to be a regular morph.

So no, I don't "touch" anything in the model, I just check the differences between 2 states of a same model that is entirely handled by the engine (which is complex, like, really complex).

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/animate1978/MB-Lab/issues/226?email_source=notifications&email_token=AKYHC3UUCKPIWAQQWLWM64TQ55PNDA5CNFSM4KFX5YB2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEJBQEBA#issuecomment-574816772, or unsubscribe https://github.com/notifications/unsubscribe-auth/AKYHC3RET2UVD2APDZ6UUITQ55PNDANCNFSM4KFX5YBQ .

Noizirom commented 4 years ago

I'm not quite sure what your asking , being that you've already found an addon for this.

On Wed, Jan 15, 2020, 6:37 PM Zion Hill Hill noizirom@gmail.com wrote:

A file called co_to_js.py will put vertices of a selected object into a .json file. https://github.com/Noizirom/Blender-Python-Tool

On Wed, Jan 15, 2020, 2:26 PM TetoTheSquirrelFox notifications@github.com wrote:

No no, it's waaaaay simpler than that. ^^ Actually I want to make a copy of the vertices of the shown model. And a python program already exists for this (it writes in a file, I just want to make a special object that stores the vertices). After that, user does his thing with Blender sculpt tools (without touching the number/name/id of vertices of course). And at the end the tool checks just the differences between the base and the sculpted, then write them in a json file in order to be a regular morph.

So no, I don't "touch" anything in the model, I just check the differences between 2 states of a same model that is entirely handled by the engine (which is complex, like, really complex).

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/animate1978/MB-Lab/issues/226?email_source=notifications&email_token=AKYHC3UUCKPIWAQQWLWM64TQ55PNDA5CNFSM4KFX5YB2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEJBQEBA#issuecomment-574816772, or unsubscribe https://github.com/notifications/unsubscribe-auth/AKYHC3RET2UVD2APDZ6UUITQ55PNDANCNFSM4KFX5YBQ .

TetoTheSquirrelFox commented 4 years ago

Nope, it's this file.

TetoTheSquirrelFox commented 4 years ago

Quick update : image Now the UI is done. I think that if the thing is finished, I will have to change things here and there, but for now I need something working for users.

TetoTheSquirrelFox commented 4 years ago

Great great news today ! ^^

I copied the great co_to_js.py int the class that is executed when user clicks on button "Store actual body vertices". I had to change things because python is handled differently when used in console and inside the plugin. So after changed every line because of this ^^, I did this :

I was worried before the try, because I feared that the data stored by MB-Lab were not the data used by Blender. So if I changed something in the body (by using sculpt tools for example), the changes would not be "seen" in MB-Lab objects. I don't know if I'm clear. Anyway, it's not the case, that is good for me.

So, now I know that it works, animate1978, the thing can be a project now ? Anyway, I have a lot of work to do.

Stay tuned ! Teto.

TetoTheSquirrelFox commented 4 years ago

It's working ! So what I did today : having a full comparison between 2 lists of vertices, with index, in order to be saved. I took one character, stored its vertices. Disabled smoothing. image Went to Edit mode, changed 1 vertex (2, because symmetric edition) image Asked for the result and voilà ! image Not sure yet, but I think that the indexes are good. Now it's not over. What I have to do

TetoTheSquirrelFox commented 4 years ago

Now I'm almost there. image As you can see, the UI changed a lot, and many parts of the name or the morphs can't be changed because they are dependent of the model.

The only thing that I have to do is to put data in an opened json, add or replace morphs, and save it. For the moment, if a morph already exists, it is replaced. Everything else seems to work.

TetoTheSquirrelFox commented 4 years ago

So V0.95 is done, is working (I hope) and was sent to Animate1978 for approval.

So what is it now ? It's a tool that allows the user to make his own morphs, based on the model he chose .

The tool : It changed a lot since I started to code. From something with many things to write before to be able to save the work, it's something now very straightforward, as the name (for the morph, for the file) must follow strict rules. However, now the engine can load many files for morphs as you want. Before this tool it was just 5 : shared morphs (for a gender), shared morphs extra, and a third one (not used by the engine), plus 2 other files for morphs specific to body types. Now with the tool you can add any files you want, the ones you made and the ones made by others.

So, what have we get ? Once the base character is made, you can choose the Morphs Creator tool and you have this: image Here is a rapid view of functions:

  1. Store base body vertices : The base model you're working on. Button to press before any change in vertices.
  2. Morph wording - Body parts -> Label for the content below.
  3. Body part : image Fun fact, it seem that we can have any body parts we want. But for the sake of sanity, I just used the standard.
  4. Name : Name of the morph. the tip shows the format. MyOwnMorph01 for example.
  5. min/max : If it's for min values of the morph, or max values. There are other values available (seen in some files) but I don't know what it's about. By the way, a morph can have just a min (or just a max), the engine doesn't mind and works well.
  6. Morph wording - File -> Label for the content below.
  7. Spectrum. whole gender or specific to a body type. Important : labels below show the name of the file, depending of your choice. And yes, you can save for both types (see below).
  8. Ethnic group : If empty, the one used by base model is used as name. If not, it overrides the base name. image
  9. Extra name : Basically the name of the author, but can be something else to separate morphs files.
  10. Autosave : If enabled, each time you save the file, a new file like m_zz99_morphs_pseudo_001.json (002, ... 999) is created with the morph. The count is reset for each session. And take care to move the files somewhere else after closing Blender to avoid overload.
  11. Quick-save work-in-progress. A little explanation here. You can change the shape of the model in edit mode or sculpt mode, but don't forget to disable 2 things : image DON'T change the index/name/number of vertices. NEVER. You just can change their location. When it's done, you can press the button. After that you can change things (or save with autosave), and press the button again, no problem.
  12. Finalize the morph. At last you save the morph :
    • If the file name is an existing file -> the file is opened, and if the morph already exists, it is replaced. So caution with standards files. Otherwise, the new morph is added.
    • If the file doesn't exist, it's created, and the morph added.
    • So, by changing gender, ethnic group or extra name, you can quickly add the same morph to many files.
    • For a morph with min and max, you have to do the work twice.
    • Important note : if the base model is not saved, or the changed model, nothing happens and a warning is shown. The morph is not saved either if the changes are too small. The engine doesn't count changes under 0.0001. So don't be alarmed if you sculpted a subtle detail but is not taken in account : it's just too small for the engine (and I didn't want to change that. Short story, the display of the number becomes scientific, like 1e-5 and Manuel didn't want to have this written in file, I guess).

Limitations :

Typical workflow :

I wrote the main things to know I think. Don't hesitate to comment. Teto.

Edit : And by the way, many many many thanks to the guy(s) who wrote the program "co_to_js.py". Without it, I think that none of this would have existed.

animate1978 commented 4 years ago

I just read the email, I have downloaded the sources and after work tonight I will go through and test this.

This is a pretty big deal, I was kind of waiting for this to come into being before I did any other work (aside from my own personal life being very busy atm)

I will also go through this issue and read through it so I can start developing some documentation.

TetoTheSquirrelFox commented 4 years ago

OK, So I had an idea this morning and was able to make it this evening. image So you can see 3 tools under "finalize the morph" :

  1. The first save all vertices of the actual body shown on screen.
  2. You can load a model and use it as a base model (you don't see the result, there's no update, sorry).
  3. The same for sculpted body.

What is the interest?

Animate1978, I've just sent to you the modified files by mail.

f_af01_morphs_teto.zip

animate1978 commented 4 years ago

I have added the code to my local copy, right now just checking it out, I still have to fully read through and test it but so far no outstanding bugs.

animate1978 commented 4 years ago

It has been committed now

animate1978 commented 4 years ago

https://github.com/animate1978/MB-Lab/blob/73072b27f07c68c474dec4a60c5030a2b09fdc0a/morphcreator.py#L225

This is causing the tester on GitHub to fail.

Lint with flake8
5s
##[error]Process completed with exit code 1.
Run pip install flake8
  pip install flake8
  # stop the build if there are Python syntax errors or undefined names
  flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
  # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
  flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
  shell: /bin/bash -e {0}
  env:
    pythonLocation: /opt/hostedtoolcache/Python/3.6.10/x64
Collecting flake8
  Downloading flake8-3.7.9-py2.py3-none-any.whl (69 kB)
Collecting entrypoints<0.4.0,>=0.3.0
  Downloading entrypoints-0.3-py2.py3-none-any.whl (11 kB)
Collecting pycodestyle<2.6.0,>=2.5.0
  Downloading pycodestyle-2.5.0-py2.py3-none-any.whl (51 kB)
Collecting pyflakes<2.2.0,>=2.1.0
  Downloading pyflakes-2.1.1-py2.py3-none-any.whl (59 kB)
Collecting mccabe<0.7.0,>=0.6.0
  Downloading mccabe-0.6.1-py2.py3-none-any.whl (8.6 kB)
Installing collected packages: entrypoints, pycodestyle, pyflakes, mccabe, flake8
Successfully installed entrypoints-0.3 flake8-3.7.9 mccabe-0.6.1 pycodestyle-2.5.0 pyflakes-2.1.1
./morphcreator.py:225:70: F821 undefined name 'simple_path'
    logger.info("Looking for the retarget data in the folder %s...", simple_path(data_dir))
                                                                     ^
1     F821 undefined name 'simple_path'
1
##[error]Process completed with exit code 1.

I will look into it when I can

TetoTheSquirrelFox commented 4 years ago

OK, I did a copy/paste and forgot to erase simple_path. So the line becomes :

logger.info("Looking for the retarget data in the folder %s...", data_dir)

And I remember : the method is not used , you can delete it. ^^

animate1978 commented 4 years ago

OK. I am working on some documentation for this, we should also do some tutorials as well because I think this opens up a lot for people. This also opens up the door to a new model which I would like to start with this one as a prototype...

https://github.com/animate1978/MB-Lab/issues/161

I was successful to a point....

https://vimeo.com/359182294

I think if a workflow could be established, this model exported correctly (I think it was a weight paint issue) and then work on some morphs as a proof of concept before we go jumping in to making "production" models.

I have yet to fully test because I have not had time yet I plan on doing some this weekend.

TetoTheSquirrelFox commented 4 years ago

OK. I've watched your video and it reminded me something. So I may be wrong, but I don't think that weight painting is the source of the problem. Groups of vertices just don't move. And the step between full move / no move is too small, and too binary. The vertex move or not. So what I'm guessing :

  1. It's a problem of vertices groups. It seems that muscles are attached to vertices by vertices groups. Your vertices could be attached to wrong group, like the fingers are attached to muscles for face ? But more I think about it, the more I think I'm wrong.
  2. But I think more about a problem of the deforming cage used to deform correctly the model when we deform it for poses. If a vertex or a group of vertices are outside this cage, they just don't move :

image here an example shown with Blenrig. Maybe I'm wrong, I don't know if MB-Lab uses a deform cage, but it really looks like it has this problem.

TetoTheSquirrelFox commented 4 years ago

I've just figured out that one method in morphcreator is really dirty. So, in method get_all_files (line 254) instead of :

    dir = data_path + "\\" + data_type_path
    list_dir = os.listdir(dir)
    found_files = []
    split_one = ""
    split_two = ""
    for i in range(len(list_dir)):
        if list_dir[i] != body_type and list_dir[i].count("extra") < 1:
            split_one = list_dir[i].split('_')
            split_two = body_type.split('_')
            if split_one[0] == split_two[0] and split_one[1] == split_two[1]:
                found_files += [dir + "\\" + list_dir[i]]    
    return found_files

that is just ugly, we should have :

    dir = os.path.join(data_path, data_type_path)
    list_dir = os.listdir(dir)
    found_files = []
    split_one = ""
    split_two = ""
    for i in range(len(list_dir)):
        if list_dir[i] != body_type and list_dir[i].count("extra") < 1:
            split_one = list_dir[i].split('_')
            split_two = body_type.split('_')
            if split_one[0] == split_two[0] and split_one[1] == split_two[1]:
                found_files += [os.path.join(dir, list_dir[i])]   
    return found_files

Much better.

And same thing in init.py, line 1052 :

file_path_name = file_ops.get_data_path() + "\\morphs\\" + file_name + ".json"

must become:

file_path_name = os.path.join(file_ops.get_data_path(), "morphs", file_name + ".json")
ldo commented 4 years ago

How about this:

    dir = os.path.join(data_path, data_type_path)
    found_files = []
    body_type_split = body_type.split('_')[:2]
    for item in os.listdir(dir):
        if item != body_type and item.count("extra") < 1:
            if item.split('_')[:2] == body_type_split:
                found_files.append(os.path.join(dir, item))
    return found_files
TetoTheSquirrelFox commented 4 years ago

Equality can work between indexes of a list like this way ? I take it! ^^ Thanks for the tip.

Edit : And I understood the rest when copying it. Not fluent in Python....

TetoTheSquirrelFox commented 4 years ago

On a side note, I discovered that the method load_json_data in files_ops.py is equal to my load_morphs_file now. I did my own method because the one from Manuel opens a file in read-only. But at the time I didn't want that because I wanted to create the file if it didn't exist. It seems that it is created anyway, so my method is useless now. Delete it.

Also, my method save_morphs_file is "perfect" for any kind of data we want to be saved in a file. So I renamed it, and put it in file_ops.py, as it's a method that will be used for many other things soon... ^^

TetoTheSquirrelFox commented 4 years ago

Animate1978, in my fork, I've just committed few changes in morphengine.py, and they are needed to allow the engine to read and load morphs created by users. I didn't see the changes in your dev branch (that I forked).

TetoTheSquirrelFox commented 4 years ago

Damn. Good news and bad news.

Bad news : The morph editor is not finished yet. Like, at all. Good news : I know now why there are methods that I didn't understand the purpose, why they exist, and how Manuel handled overlapping morphs in order to have nice deformations any time.

Short story : As I tried things tonight to separate base expressions morphs to regular morphs (for body), I was shocked about morph names that had a bizarre name like "Torso_BreastMass-BreastTone-Mass-Tone_max-max-min-min" What ?!? The first part (Torso) is OK, it's about the torso, no problem. But "BreastMass-BreastTone-Mass-Tone". I quickly understood that in fact it's about 4 morphs in 1, aka a combined morph. So "max-max-min-min" is about the min/max of each part. So I checked this (in human_female_morphs.json). And I found this : "Torso_BreastMass-BreastTone-Mass-Tone_min-min-min-min": "Torso_BreastMass-BreastTone-Mass-Tone_min-min-min-max": ... "Torso_BreastMass-BreastTone-Mass-Tone_max-max-max-min": "Torso_BreastMass-BreastTone-Mass-Tone_max-max-max-max": 16 combined morphs that are a combination of 4 "simple" morphs (and they displayed separately in Blender, like regular morphs, it's not an "all in one") and min/max values, so 16 morphs in total.

Useful to know, for later : Manuel uses 2 subclasses in humanoid:

  1. HumanCategory : Keeps all parts of a body, as a category. Arm, body, leg, and so on.
  2. HumanModifier : A modifier is a body part that belongs to a Category, with all properties needed to keep the morphs and apply them to a model.

So, some Modifiers keep properties for 1, 2 or 4 parts (the biggest I found), some parts can even be in multiple modifiers (for example, BreastMass is in a Torso_"BreastMass-BreastTone-Mass-Tone", as already said, but also "Torso_BreastMass-BreastScaleY", "Torso_BreastMass-BreastPosX" and so on. One thing that can't be mixed, is the category. all BreastMass combinations are in Torso, no other category.

So, after few research about the methods/object that use those 2 sub-classes, I think this : The combined morphs is to assure that all body parts involved are morphing nicely, and combination of a huge part, for example, and a tiny one, in the extremes, gives something believable, not ugly or weird.

But for me, and I don't like that, ^^ that also means that I have to add a new editor : "combined morphs creator" and rename the actual "simple morph creator"

I'll do the new tool when the new model will be done, or if I code it before, it will be useful only with new models that have no morph. The tool will be easy to do (I 'm thinking about it while writing), because basically what I have to do is to dispatch all simple morphs of a category, the user sculpt all combinations, save them (like the existing tool), and when it's done, he deletes the base morphs used to create combinations. The name will be automatic, as usual, and I imagine that the engine will do the rest. Note : The method where we can see how a morph name is split and put in category and modifier is "init_character_data(self, morph_name)" in humanoid.

Good night ! ^^ Teto.

TetoTheSquirrelFox commented 4 years ago

OK, the work is not finished yet, but I'm getting something. So my work this week-end was about the Combined Morph Creation, as explained above. What's going on for now ?

  1. I reorganized the whole tab a little, and has 3 parts. 1st the 2 main categories, editing model and create model. 2nd is about tools available while editing/creating model. 3rd is the content of the selected tool. image

  2. If a compatible model is not selected, you can't do anything, you're stuck. image

  3. About the Combined Morph Creation, it's a complete (well, for the moment, buttons for saving are missing) tool that allow you to create combined morphs from simple morphs : image The image here shows the max combination we can do.

  4. Something important : you can't create a combined morph if simple morphs are already combined morphs (in file). For example here; all morphs I want to use are actually used in combined morphs somewhere. So you can't use them to create a new one. I'll explain the workflow in next post.

  5. Since morphs are compatible, you can create your combined morph : image It works exactly like Simple Morph Creator. The name is automatic (and long), you choose if it's for a whole gender or specific to an ethnic body. You add an extra name (important here, see next post about that), and when your sculpt is done you can save.

  6. Note : I'll add a button to update the character. When clicked, all values of selected morphs will be put in min/max values according the choice made. Then you sculpt the model, store the modification, and save them if you're satisfied with your work. No difficulty here.

So in the next post I talk about the workflow, guidelines (I think) for creating the morphs of a model. (it's for future documentation, that's why it's a separated post). I'll edit it sometimes, with images and stuff.

TetoTheSquirrelFox commented 4 years ago

What is the workflow to create morphs to a model ?

First, what is a morph ? A morph is a group of vectors that move vertices they are attached on. Each morph corresponds to a specific body part, and the name explains what it does. For example Torso-SizeX is a morph that change the size of the torso along the X axis. The first part of the name is the category where the morph is. A same morph can't be in 2 different categories. And each morph has a minimum value(0) and a maximum (1). For the moment we can't exceed theses values.

Different types of morphs ? For the user, no. They don't exist after finalization, except for the morphs involved in face expressions, they are changed in shapekeys, and used to create expressions like angry, or happy.

For the creator, it's different, you have 2 types.

  1. Simple Morphs : They change the size/position/shape of a body part, and they don't overlap other morphs too much (or it doesn't matter, the result fits well in any case).
  2. Combined morphs : You see them as simple morphs when you morph a model as an user, but in reality they overlap each over so much that the result would be weird or ugly if they would stay simple morphs. For example, a torso can be fat, athletic, normal, and so on. The tone of the torso has consequences on the mass, etc. So the morphs can't be separated, they must be combined to always work nicely. More about this below.

So, what is the general workflow when creating morphs ?

  1. After the creation of the model, and when all vertices are frozen, you will use mainly 2 editors to create morphs, "Simple Morph Creation" and "Combined Morph Creation".
  2. First thing to do is to choose wisely all the morphs you want to create and try to have a complete list before starting to sculpt.
  3. In this list try to separate the morphs that will stay simple and the ones that will be combined. After a while, changing will be difficult and source of problems.
  4. Read the documentation to know about the use of the tools. But, basically, you'll create 2 files for your morphs. 4.1. The main file where you put your simple morphs, and your combined morphs. 4.2. and intermediary file where you store the simple morphs that are used to create the combined morphs.

The workflow for creating combined morphs :

  1. You create a dedicated file where you store every simple morphs that you want to use to create combined morphs.
  2. You create/sculpt them and store the results with "Simple Morph Creator" tool.
  3. Quit Blender and reopen it.
  4. Use the "Combined Morph Creator" to choose those morphs (for mix of 2, 3 or 4 simple morphs). Play with min/max values. For each combination you have to sculpt the result and store it. So for combination of 2 simple morphs, you have to create 4 sculpts. For 3 it's 8 and for 4 it's 16. You save the result as a simple morph, it's the same workflow. Important, save the morphs in another file, not the one where the simple morphs are.
  5. When all these combinations are made and saved in the dedicated file, you can either create new combined morphs (and they can re-use simple morphs already used), or delete/move the file where the simple morphs are. Quit Blender, reopen it, and the combined morphs are shown as simple morphs, but their behavior depend of other morphs used for the mix.
TetoTheSquirrelFox commented 4 years ago

A quick update. I'm finishing tonight the "Combined Morph Tool", and I was thinking that the "Simple Morph Tool" should have a refreshing, so I improved few things like displayed texts and tips. I also reworked how it looks, I think it's more obvious : image Another example, where all is completed before finalizing : image

TetoTheSquirrelFox commented 4 years ago

So, "Combined Morph Creator" is complete. Not tested yet, because I'm done this evening, and I fear that all I did is useless, because even if the principle is good (combined morphs are made to make nice results when simple morphs heavily overlap), the way to achieve it is far from I imagined. So it's better for my nerves to postpone to another day. ^^

Anyway, a view of the UI : image I have already explained how the 1st half works, and the the 2nd works as simple morph creator, they even share the same components.

Anyway, cross fingers, I'll test probably tomorrow.

TetoTheSquirrelFox commented 4 years ago

@animate1978 , an interesting note that I discovered tonight, that could be mentioned in documentation :

  1. Above all elements for morphs (in MB-Lab, I don't talk about the tools I made) you have 3 specials morphs that work globally : character_age, character_mass and character_tone
  2. Mass and Tone are linked somehow to morphs. If the name of a morph, whatever it is, has "Mass" or "Tone" in its name, the neutral value changes accordingly (but you can change it after). I think that it has a lot to do with combined morphs. I fear that I was wrong since the beginning...
animate1978 commented 4 years ago

It is ok, you have been not only building a lot but deciphering what MB-Lab really is. Mistakes happen and revelations happen at varying times. It is interesting to know that the Mass/Tone/Age is a global morph though, makes sense come to think about it.

I have been working on moving some of your writing here to the docs, I haven't made any commits yet though, formatting it.

TetoTheSquirrelFox commented 4 years ago

No problem. ^^

This evening, I didn't make test about Combined Morphs, because I think that it will be huge to test it (and I'll need to comment my tests for documentation) so I'll do this next week-end.

But before that, I decided to create new tools, again, for creating phenotypes (aboriginal, euroartic, ...) and presets (specialtypes for example) that corresponding to Character Library.

Finished the 1st one (almost, I have to format the content of the file), you can see a teaser below : The UI is a copy of morphs elements from MB-Lab put here for convenience. The 2 tools share the same morphs, so... image As usual, you have info labels to help the creator, and when the name has the good format, you can save : image If the file already exists, there's a warning label.

Tomorrow I'll start the other tool, that seems more funky (for finding automatically the path).

TetoTheSquirrelFox commented 4 years ago

@animate1978 , I read you post on Patreon, I was sure that this tool should please you. ^^ You talked about your fight with phenotypes weeks ago somewhere.

So, the tool is ready, and should work. I did few tests, nothing wrong for me. Have fun with it. Limitation : When your phenotype is done, you have to create a new Blender project (but without exiting it), and recreate the character.

Anyway, I almost made the 2nd related tool to Character Library, aka Presets. The save is not working for now (because... tired) but should not be difficult to do, as the principle is the same for Expressions and Phenotypes.

By the way, the files created have a nice indent now, I read the doc about json, and found the way to indent the data in file.

Now, how it looks like : image

Side note : In fact, morphs are used many times to create all kind of bodies from a single model, before the user can use them again. I'll try to write something about it this week-end. Should be useful for general documentation.

TetoTheSquirrelFox commented 4 years ago

So the second tool about Character Library is done. I didn't test it extensively, but it should work. Since previous post, I discovered that sometimes the materials are saved in the file for a reason. So I added the possibility to save (and work with) materials. image if material is not selected : image and if there's no name : image

I delay the extensive test about Combined Morph Creator because of the way age/mass/tone are working. They use a special file, under /data/transformations where all morphs are changed by a linear interpolation, in order to change the age/mass/tone of a body. The file is different for most type of body, so it's interesting to also have a tool for that, as I think that it's very smart to have a body that can change by 3 cursors (age aka age, mass aka fat and tone aka muscle) without to have to change individually all morphs. And I think that understanding the principle will help me to understand how Combined Morph Tool should work.

TetoTheSquirrelFox commented 4 years ago

I'm done tonight.

So it's a new tool that is important because it allows the creator to change something important, the behavior of this :

image

So what's going on for now : image The preselection is done, and everything about saving file is done too, except the button for that. We can also import a file to use it as a model.

How does it work ? Basically age, mass and tone change directly all morphs (except expressions). The trick here is that the cursor for age, for example has ONE value, from -1 to 1. However, this property is linked to other morphs (number can vary) that change body shape. As we just can't do result = age * body_part AND the min for age for this body_part can be different of the min of the morph itself, the engine must do a linear interpolation from -1/+1 of the age and 0/1 of the body_part. And that is done by "transformations" file. Example :

TetoTheSquirrelFox commented 4 years ago

I'm done for tonight, but here is a quick wip review about the new tool for transformations, aka linear interpolation between Age, Mass and Tone, and the morphs, to quickly give fat, muscle or age to a character without having to use morphs one by one : image So you can see that morphs can be used many times. I have a lot of work to do :

TetoTheSquirrelFox commented 4 years ago

OK. Good news and bad news (and something funny) :

TetoTheSquirrelFox commented 4 years ago

Debug step. Was more difficult than expected, because during the day I was thinking about some little improvements, so... more time on them. Short story : I added the possibility to recover a state of the database. For example, while playing with cursors I am pleased with the result, I can say : please save this step. After that, if I play again but want to recover the previous step, I can. The step is not saved on disk, it's a kind of undo. Why that ? Because the tool doesn't work in real time. And saving on disk for each step would be very tedious very quick imho. So as a workaround, you can quick-save a step on memory, save it on disk (no counter this time, you change the name, it will be fast too), load saved files. The tool is not a tool that you use every day anyway.

I'm just annoyed that I can't show changes in real-time, to many things to change in the engine, I think that there are better works to do for now. The addon should be re-written from scratch anyway, in a creator point of view, not as an end user.

By the way, setattr has weird initialization sometimes, I wasted time because of that. For example if I do a setattr with a value of 0.45, sometimes the engine puts 0.499999999999122858 in memory.

But most of the time was used to link the change between the GUI (by user) and the data in engine. Now, aside debugging and testing, I have to finish the save step/recover step thing, and allow to save in file, of course.

And since that is done, I fix the existing files, that have errors.

animate1978 commented 4 years ago

OK I have merged your code, fixed the conflict. @TetoTheSquirrelFox please make sure you pull before making commits, there was duplicate entries made during the conflict merge that I fixed. Nothing you did really it was just how the code merged during the conflict resolution.

TetoTheSquirrelFox commented 4 years ago

Sorry I don't know how it works, what do you mean by pulling, reimport the project from your repository ?

TetoTheSquirrelFox commented 4 years ago

@animate1978 I downloaded your repository, I guess it will work fine now.

I've just lost almost 2 weeks of work. I was struggling with the transformation tool, how link the content of UI with internal data base of the model, how to update in real time... (watch post above for more details). The solution was so simple (I add the idea this morning). I just have to do the same kind of things that I did for morphcreator : using the prop to display morph and play with them to update the model in real time, then save the work step by step, here there will be 4 steps (see below): image So :

The thing that hurts is the transfor.py file. It's almost empty now. ^^

@animate1978 The tool is not finished yet but I push it to see if you have problems to do the commit.

animate1978 commented 4 years ago

Oh no, 2 weeks?? OMG I am so sorry, what happened? Was this because you pulled from this repository?

Good to see that this is coming together though, very impressive. I haven't merged the code yet but it should be ok to merge I will do that later on tonight or tomorrow.

TetoTheSquirrelFox commented 4 years ago

No, no, don't worry ! ^^ It's just that my 2 weeks on the job were useless because I found a better way to handle this tool. ^^ So have to rewrite it from scratch !

TetoTheSquirrelFox commented 4 years ago

Quick update : My last tool related to morph is almost finished. Tomorrow morning I will be able to push the commit I think. In this tool about transformations (to change age, mass and tone directly) I wrote a small tool that checks the validity/compatibility of the file used by the model shown on screen. Mays be useful if, for a model, people add new morphs for example.

So the tool is also useful to see the errors in actual files used by Manuel, and I'm fixing them. But I won't do it for anime character. See below all errors the file has: anime_female_base_transf.json.txt

Obviously the file is either:

TetoTheSquirrelFox commented 4 years ago

Little post about few UI things I did. The tool about transformations (age/mass/tone thing) is over, and it's not that good, but I'll talk about that later. While finishing that tool, I also made few little changes in the UI (see below) : During creation phase, I tried to have a more clear separation between "topics": image I think that doesn't touch the changes that @Anyeos suggests. All about age/mass/tone is separated from the rest, and also the "after-creation tools".

And about MB-Dev, I changed the organization and icons to be more coherent with MB-Lab's UI. image I took icons from the other tab, and changed the order of the tools, to be more an the workflow that should have a creator.

TetoTheSquirrelFox commented 4 years ago

So, about my last tool, "Age, Mass & Tone" transformation.

I must say that I'm a little disappointed. But first, the changes since my last posts : image

  1. In load/save parts you have 2 buttons (if file name is good) :
    • Load step. When pressed, the button loads (if file exists and is valid) the data for the category (age, mass, tone) and extreme (min or max) that the user has selected. Important : see the part "limitations" below.
    • Transformations are about age, mass and tone. And for each of them, you must have 2 values, min and maxi. So you have to do 6 steps if you want to create/modify a "transformation" file. This button allows you to save each step. The name must stay the same of course. When you save the last step, your file is complete and ready to be used. The file can even be used before, the engine doesn't crash.
  2. Tools.
    • Check compatibility : Loads a a transformation file you want, and checks if the morphs inside are compatible with current model on screen. The result is stored in a txt file with same name (+ .txt). It shows, for each category, the morphs that are not used by the engine, for a reason (bad name most of the time). Interesting if the user want to check if a file for another model can be used nevertheless.
    • Export current model : Export the data base of the current model (not the stuff done by the user) in a file. The icon is "freeze" because the name used is the name written in the text area, no dialog window to choose the name.
    • Import for current model : import a transformation file for the current model. When imported, user can play with cursors age, tone and mass to watch the results on the model.

Limitations : The tool works, no problem, but is also "What You See Is Not Completely What You Get" when you "Load step". Here the things to do to see what's going on :

animate1978 commented 4 years ago

Well it is better than before, when we had no tools so it is ok.

I've been doing trial and error with the GUI and little success so I am sure I am missing something just haven't gotten it yet. I have to look over that patch again and see.

TetoTheSquirrelFox commented 4 years ago

This is a special post, for the documentation. As always, bad english, and I'll edit it time to time. So what's about ?

This addon was developed to create, rig, and animate various types of human, from a "root model". The difference with MakeHuman is that this older tool made by the same author, Manuel Bastioni start with only one model. No gender, you can evolve your model from baby to very old, and few other things. Cool, but brings a lot of problems (for genders especially) that Manuel didn't want for his new tool. And MakeHuman is a separated program, much more complicated to develop than an addon for a free program like Blender, especially when this program can compete with the best on the market, especially since version 2.79.

This introduction is a way to introduce the fact that the addon is more or less MH directly in Blender, using all stuff already done in Blender, so MB doesn't have to bother about. So that means that a large parts of MB just handle data that are used by Blender, and the only thing where MB focusing on is the handling of the model and links with Blender functions like rendering, hair, rig and so on.

In order to do that correctly, Manuel divided the use of his addon in 3 distinct steps :

  1. The setting of the scene where the character is created. If the user wants to use evee, the lights for rendering and so on. image
  2. The step of the creation of the character. Its gender, phenotypes, proportions and so on. image
  3. After finalization of the character, all tools for rigging, shaders, hair and so on. The user can't go back to change his model, at least with the addon's tools. All elements handled by the addon that can be handled by Blender are transferred to Blender elements, like shapekeys. image

So the user must understand that step 2 and 3 are clearly separated. More than this, you can do things in step 2 that you can't in step 3 and vice-versa. In fact, almost nothing can be done in both of them. So user must be aware of that and save his work during each step just in case.

So step 2 is the core of the program and can be resumed in one word : Morph. Except skin textures, all is related to morphs and everything that is related to : vertices, shapes. BBoxes and vertices groups are important, but they are used only after finalization.

When the session starts, all data useful for step 2 and step 3 are loaded and can be roughly resumed like this :

  1. The user chooses the model (human, anime), gender in step 1 and initiate the character.
  2. During initialization of step 2, aside loading data useful for step 3 :
    • The model is loaded.
    • The morphs made for this model are also loaded. The are used for many things during the creation process.
    • 1st, the morphs are used first for the phenotypes (African, Caucasian, ...)
    • 2nd, they are also used to create variation of the body as a whole : Age, Mass, Tone. And they are also used to create presets, to help user. image
    • 3rd, again, the same morphs are available to the user to create his own character. That means that some body parts can be morphed 3 times by the same morphs (and the effects are cumulative on the final result) The other data handled by the engine are updated accordingly, the user doesn't have to worry about them. Skeleton, rigs, muscular system for poses and animation, expressions, ...
  3. You have some tools that save times, like a basic posing system, to watch the proportions of the model, smooth body, skin editor. image image
  4. You even have tools to create a bunch of characters with just few clicks, and with restrictions, in order to have the kind of variations you want : image image

Of course you can save your model (in a light-weighted json file). More explanations about the tools are available in the documentation. The thing that is important here is all this stuff must be done before finalizing the model and go to step 3. And all stuff is provided by the engine, not by Blender, its rule here is only to display the model. It's not the case in step 3.