Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

Adding new BlendShape from script - Buggy Deformation result[FIXED]

Discussion in 'Editor & General Support' started by DeathApocalypse, Feb 12, 2020.

  1. DeathApocalypse

    DeathApocalypse

    Joined:
    Sep 29, 2016
    Posts:
    10
    Hi, i've made a script that converts Meshes into SkinnedMeshRenderer, and creates a BlendShape for it.

    Code (CSharp):
    1. private void AddMorph(GameObject _ref, GameObject selection_mesh)
    2.     {
    3.         Mesh _m = new Mesh();
    4.  
    5.         // _selection - Bounds for selecting group of vertices within.
    6.         _selection = new Bounds(selection_mesh.transform.position, selection_mesh.transform.localScale);
    7.  
    8.         // movement delta for future group of vertices.
    9.         Vector3 newDelta = new Vector3(0, -0.4f, 0);
    10.  
    11.         // name for the future blend shape.
    12.         string MorphName = "Custom[50-250]";
    13.  
    14.         //
    15.         // Convert Mesh Renderer to Skinned Mesh Renderer, and create and instance of the shared mesh.
    16.         //
    17.         if (_ref.GetComponent<SkinnedMeshRenderer>() == null && _ref.GetComponent<MeshRenderer>() != null)
    18.         {
    19.             _m = Instantiate(_ref.GetComponent<MeshFilter>().sharedMesh);
    20.             Destroy(_ref.GetComponent<MeshRenderer>());
    21.             Destroy(_ref.GetComponent<MeshFilter>());
    22.             _ref.AddComponent<SkinnedMeshRenderer>();
    23.             _ref.GetComponent<SkinnedMeshRenderer>().sharedMesh = _m;
    24.         }
    25.         else if (_ref.GetComponent<SkinnedMeshRenderer>() != null) // Create instance of shared mesh.
    26.         {
    27.             _m = Instantiate(_ref.GetComponent<SkinnedMeshRenderer>().sharedMesh);
    28.             _ref.GetComponent<SkinnedMeshRenderer>().sharedMesh = _m;
    29.         }
    30.         else return; // if object has no renderer at all, stop the script execution.
    31.  
    32.         // Assign the new mesh we instantiated before.
    33.         _ref.GetComponent<SkinnedMeshRenderer>().sharedMesh = _m;
    34.         // create array with deltas.
    35.         Vector3[] newVertexDeltas = new Vector3[_m.vertices.Length];
    36.  
    37.         for (int y = 0; y < newVertexDeltas.Length; y++)
    38.         {
    39.             if (_selection.Contains(_ref.transform.TransformPoint(_m.vertices[y])))
    40.             {
    41.                 // each vertex found within the _selection bounds, gets the delta.
    42.                 newVertexDeltas[y] = newDelta;
    43.  
    44.                 //GREEN draw line - current position of vertices.
    45.                 Debug.DrawLine(
    46.                     _ref.transform.TransformPoint(_m.vertices[y]),
    47.                     _ref.transform.TransformPoint(_m.vertices[y] + _m.normals[y] * 0.05f),
    48.                     Color.green, 1000000.0f);
    49.  
    50.                 //MAGENTA draw line - path of each vertex from initial position to delta position.
    51.                 Debug.DrawLine(
    52.                     _ref.transform.TransformPoint(_m.vertices[y]),
    53.                     _ref.transform.TransformPoint(_m.vertices[y] + newDelta),
    54.                     Color.magenta, 1000000.0f);
    55.  
    56.                 //BLUE draw line - position of each vertex in it's delta position.
    57.                 Debug.DrawLine(
    58.                     _ref.transform.TransformPoint(_m.vertices[y] + newDelta),
    59.                     _ref.transform.TransformPoint((_m.vertices[y] - _m.normals[y] * 0.05f) + newDelta),
    60.                     Color.blue, 1000000.0f);
    61.             }
    62.             else
    63.             {
    64.                 //RED draw line - position of each vertex that are not within the _selection bounds.
    65.                 newVertexDeltas[y] = Vector3.zero;
    66.                 Debug.DrawLine(
    67.                     _ref.transform.TransformPoint(_m.vertices[y]),
    68.                     _ref.transform.TransformPoint(_m.vertices[y] - _m.normals[y] * 0.05f),
    69.                     Color.red, 1000000.0f);
    70.             }
    71.         }
    72.  
    73.         // Create the new blendshape with vertecies deltas.
    74.         _m.AddBlendShapeFrame(MorphName, 100f, newVertexDeltas, null, null);
    75.     }
    And within the editor, everything looks correct!

    GREEN - current position of vertices.
    MAGENTA - path of each vertex from initial position to delta position.
    BLUE - position of each vertex in it's final delta position.
    RED - position of each vertex that are not within the _selection bounds. stay equal to Vector3.zero.
    blendshapeBug.jpg



    BUT, when i try to see the blend shape in action, i get this:
    blendshapeBug2.jpg


    When i try the same script, but just moving the vertices to their deltas, it also looks OKAY:
    blendshapeBug33.jpg

    my question is simple.

    WHAT am i doing wrong in the process of making a new BlendShape data for the mesh??
     
  2. DeathApocalypse

    DeathApocalypse

    Joined:
    Sep 29, 2016
    Posts:
    10
  3. DeathApocalypse

    DeathApocalypse

    Joined:
    Sep 29, 2016
    Posts:
    10
  4. DeathApocalypse

    DeathApocalypse

    Joined:
    Sep 29, 2016
    Posts:
    10
    okay, i've solved that.

    just needed to run tangets and normal recalculation after adding the blend shape.

    Code (CSharp):
    1.        
    2.         // Create the new blendshape with vertecies deltas.
    3.         _m.AddBlendShapeFrame(MorphName, 100f, newVertexDeltas, null, null);
    4.         _m.RecalculateNormals();
    5.         _m.RecalculateTangents();
     
    ciel712, jirimotejlek and urbiman like this.
  5. urbiman

    urbiman

    Joined:
    Dec 3, 2019
    Posts:
    3
    Thanks for posting that, based on the results I saw in Unity I would have never come up with that solution I guess. Should definitely be something that is added to the documentation.