Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

get skinned vertices in real time

Discussion in 'Editor & General Support' started by benblo, Dec 10, 2008.

  1. unitylepi

    unitylepi

    Joined:
    May 21, 2018
    Posts:
    34
    Can I ask what the BakedScale is for? Does the baked mesh have different vertex properties than the normal mesh?
     
  2. CodeKiwi

    CodeKiwi

    Joined:
    Oct 27, 2016
    Posts:
    119
    When you import a fbx skinned mesh it seems to set the mesh transform scale to 100 (from the model import settings: convert units cm to 0.01 m). Normally I use baked meshes for calculations and don’t render it so I apply the scale directly to the vertices. The scale could also automatically be calculated from the parent game object transforms. If you just wanted to bake it to a mesh for rendering (maybe some special shader effect), then it would probably be better to avoid scaling the verts and just set the transform scale to match the source skinned mesh. The best option would be to export it at the correct scale and import it with the convert units tickbox off, then remove all BakedScale code.
     
  3. unitylepi

    unitylepi

    Joined:
    May 21, 2018
    Posts:
    34
    [QUOTE="The best option would be to export it at the correct scale.[/QUOTE]

    Thanks!

    Maybe this is the wrong place for this question but there are very few places where bakemesh is being discussed (and the documentation is exactly 3 lines :( ). I have a feeling that the baked mesh of an object instance in the scene does not have the same orientation as the actual mesh in the scene. Any idea why? Or how to compensate?

    I visualize the bakemesh as such:

    Code (CSharp):
    1.     private void ShowBaked()
    2.     {
    3.         bakedMeshM = new Mesh();
    4.         smrM.BakeMesh(bakedMeshM);
    5.         smrM.sharedMesh = bakedMeshM;
    6.     }
    7.  
    The returned mesh looks like this(https://tinyimg.io/i/16lFs4s.png):


     
  4. unitylepi

    unitylepi

    Joined:
    May 21, 2018
    Posts:
    34
    Looks like that's a problem due to blender orientation vs unity. It works when I do:

    Code (CSharp):
    1.     Vector3 blenderInvRotation = new Vector3(-90, 0, 0);
    2.     Vector3 blenderRotation = new Vector3(90, 0, 0);
    3.  
    4.     private void ShowBaked()
    5.     {
    6.         bakedMeshM = new Mesh();
    7.  
    8.         smrM.transform.localRotation = Quaternion.Euler(blenderInvRotation);
    9.  
    10.         smrM.BakeMesh(bakedMeshM);
    11.  
    12.         smrM.transform.localRotation = Quaternion.Euler(blenderRotation);
    13.  
    14.         smrM.sharedMesh = bakedMeshM;
    15.     }
    Now looking for a way to test the smr to automatically see whether it needs this trick, anybody any ideas?

    Also it occurs to me that often times we only want the current state of the vertices, so instead of getting the complete baked mesh (with tris, norms, uvs, bones etc) it would be many times faster if we could just get the baked Vertices only. Any way to do this?
     
    Last edited: Jan 7, 2021
  5. CodeKiwi

    CodeKiwi

    Joined:
    Oct 27, 2016
    Posts:
    119
    Interesting, I don’t normally reassign the mesh to the same skinned mesh. I normally assign it to a new mesh renderer like below.

    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. [RequireComponent(typeof(SkinnedMeshRenderer))]
    4. public class BakeTest : MonoBehaviour
    5. {
    6.     void Start()
    7.     {
    8.         var smrM = GetComponent<SkinnedMeshRenderer>();
    9.         var newObj = new GameObject(name + "_mesh");
    10.         newObj.transform.SetParent(transform.parent);
    11.         var mr = newObj.AddComponent<MeshRenderer>();
    12.         mr.material = smrM.material;
    13.         var filter = newObj.AddComponent<MeshFilter>();
    14.         var mesh = new Mesh();
    15.         var origRot = transform.localRotation;
    16.         transform.localRotation = Quaternion.identity;
    17.         smrM.BakeMesh(mesh);
    18.         transform.localRotation = origRot;
    19.         filter.mesh = mesh;
    20.     }
    21. }
    I’m also using Blender, it feels like you should be able to just store the original rotation, set it to the identity, bake it and restore it like in the code above.

    One odd thing I found was that the Unity version of BakeMesh was around three times faster than my version even though my version only gets vertices. I’m not sure what optimizations BakeMesh uses, maybe DOTS related? I think using a compute shader would also still be slower as it tends to lock the GPU when transferring data (unless it had a very large number of verts).
     
    unitylepi likes this.
  6. unitylepi

    unitylepi

    Joined:
    May 21, 2018
    Posts:
    34
    [QUOTE="I normally assign it to a new mesh renderer like below.[/QUOTE]

    You're saving my life here :)
    By using Identity it should probably also work for non-blender models, right?

    Turned it into a GetBakedMesh() method for calculations on the mesh. Had to add some scaling code as my model is already instantiated in the scene, but it's parent object sets the overall scale of the model. Not sure if this is the best way to compensate, I assume if the method somehow takes waaay too long, you may see the original model glitch and become a giant for 1 frame. (but this is probably also true for the localRotation part...)

    Code (CSharp):
    1.  
    2.     private void GetBakedMesh()
    3.     {
    4.         bakedMeshM = new Mesh();
    5.  
    6.         // set model mesh at default orientation and scale
    7.         Quaternion origRot = smrM.transform.localRotation;
    8.         Vector3 orgScale = smrM.transform.parent.localScale;
    9.  
    10.         smrM.transform.localRotation = Quaternion.identity;
    11.         smrM.transform.parent.localScale = new Vector3(1.0f, 1.0f, 1.0f);
    12.         {
    13.             smrM.BakeMesh(bakedMeshM);
    14.         }
    15.         smrM.transform.parent.localScale = orgScale;
    16.         smrM.transform.localRotation = origRot;
    17.  
    18.         bakedMeshM.GetVertices(bakedVertsM);    
    19. //        vertsMLocalToC = smrM.transform.ToLocalCoordsOfObject(smrC.transform, bakedVertsM);
    20.     }
    21.  
     
    Last edited: Jan 8, 2021
  7. Aldeminor

    Aldeminor

    Joined:
    May 3, 2014
    Posts:
    18
    @CodeKiwi
    Thanks, I successfully used your optimized version with mesh baking to attach certain transforms to skinned body surface!
    Here's basically production-ready script stripped off of 'slow' algorithms and pumped with some cool stuff:
     

    Attached Files:

    CodeKiwi likes this.