- Home /
Realtime vertex position of a SkinnedMesh
Hello, I am making a script that should be able to instantiate objects for every vertex detected on a mesh, now I already managed to do this for static objects, as it is simply iterating with a loop trough every vertex of the Mesh.vertices function.
My question now is, since there is no vertices function inside the SkinnedMesh. How would one approach this?
I do not ask for ready to go scripts or solutions. Just a push in the right direction.
note: I script with JavaScript so if you have code related answers please take this into account.
Many greetings and merry Christmas.
Answer by angelonit · May 08 at 10:16 PM
Sorry to necro but this worked for me so here it is (in C# for those who, like me, arrived at the question in the far future):
Transform tOwner;
SkinnedMeshRenderer skinnedMeshRenderer;
List<Vector3> meshVertices = new List<Vector3>();
public void GetVertices()
{
Mesh mesh = new Mesh();
skinnedMeshRenderer.BakeMesh(mesh, true);
mesh.GetVertices(meshVertices);
tOwner = skinnedMeshRenderer.transform;
}
public Vector3 GetPositionFromVertex(int i)
{
Vector3 worldPosVertex = tOwner.localToWorldMatrix.MultiplyPoint3x4(meshVertices[i]);
return worldPosVertex;
}
Haha wauw, I did not expect a reply 9 years later. Since in the current version of Unity your method is more fitting I will update this as the correct Answer :). If my memory is correct, I also ended up creating a similar solution to this back in the day 9 years ago. Totally forgot about this post, should have updated it and spared you the trouble.
Haha I guess some stuff keeps being needed forever :)
PS: Edited the "new mesh" inside the function, since I forgot it outside :(
Answer by MarkD · Dec 31, 2013 at 03:28 PM
After a long few days search I found the answer here
I converted the script to JavaScript. Note that depending on vertices this can be very very slow. But it does the job, vertex position of the animated mesh. Place this script on your skinnedmesh renderer.
#pragma strict
/// <summary>
/// Compute a skinned mesh's deformation.
///
/// The script must be attached aside a SkinnedMeshRenderer,
/// which is only used to get the bone list and the mesh
/// (it doesn't even need to be enabled).
///
/// Make sure the scripts accessing the results run after this one
/// (otherwise you'll have a 1-frame delay),
/// </summary>
@HideInInspector
var mesh: Mesh;
@HideInInspector
var skin: SkinnedMeshRenderer;
@HideInInspector
var vertexCount:int=0;
@HideInInspector
var vertices:Vector3[];
//@HideInInspector
// var normals:Vector3[];
function Start() {
skin = GetComponent(SkinnedMeshRenderer);
mesh = skin.sharedMesh;
vertexCount = mesh.vertexCount;
vertices = new Vector3[vertexCount];
// normals = new Vector3[vertexCount];
//animation example
for (var b:int= 0; b < mesh.vertexCount; b++){
var cube : GameObject= new GameObject.CreatePrimitive(PrimitiveType.Cube);
cube.name=b.ToString();
cube.transform.localScale.x=0.1;
cube.transform.localScale.y=0.1;
cube.transform.localScale.z=0.1;
}
}
function LateUpdate(){
var boneMatrices: Matrix4x4[] = new Matrix4x4[skin.bones.Length];
for (var i:int= 0; i < boneMatrices.Length; i++)
boneMatrices[i] = skin.bones[i].localToWorldMatrix * mesh.bindposes[i];
for (var b:int= 0; b < mesh.vertexCount; b++){
var weight:BoneWeight = mesh.boneWeights[b];
var bm0:Matrix4x4 = boneMatrices[weight.boneIndex0];
var bm1:Matrix4x4 = boneMatrices[weight.boneIndex1];
var bm2:Matrix4x4 = boneMatrices[weight.boneIndex2];
var bm3:Matrix4x4 = boneMatrices[weight.boneIndex3];
var vertexMatrix:Matrix4x4 = new Matrix4x4();
for (var n:int= 0; n < 16; n++){
vertexMatrix[n] =
bm0[n] * weight.weight0 +
bm1[n] * weight.weight1 +
bm2[n] * weight.weight2 +
bm3[n] * weight.weight3;
}
vertices[b] = vertexMatrix.MultiplyPoint3x4(mesh.vertices[b]);
// normals[i] = vertexMatrix.MultiplyVector(mesh.normals[i]);
//animation example
var fetch= GameObject.Find( b.ToString());
fetch.transform.position = vertices[b];
}
}
btw: That's not Java it's UnityScript which is similar to Javascript but it has no relation to Java at all.
@Bunny83 Sorry, I meant JavaScript (which is a legit na$$anonymous$$g for UnityScript it's in the docs). You are right, I'l edit it out.
Answer by Bunny83 · Dec 31, 2013 at 04:17 PM
Unity has a new method called SkinnedMeshRenderer.BakeMesh which lets you create a "snapshot" of the current Mesh-state.
Doesn't that slow down your system even more? I use it for tracing each vertice every frame, the script above is slow. But isn't baking slower?
But thanks for the headsup, I will check it out.
no, it certainly isn't slower than skinning each vertex manually. The Skinned$$anonymous$$eshRenderer is made for skinning.
I don't use it to skin the vertices manually, I used it to transform objects at every vertex position. For instance for each vert in the mesh a cube will follow its position. Or doesn't that make any difference in this case?
EDIT: It seems that the performance is the same (for placing transforms at vertex position), also with Bake$$anonymous$$esh I get the wrong vertex orientation, all the results are rotated wrong or in negative space. To bad, it would be much easier since it requires only 3 lines of code with bake$$anonymous$$esh.
thx anyway
I'm not sure what you mean... The vertex positions of the baked mesh are of course in local space, like always. If you need them in world space you have to use TransformPoint of the transform the mesh is rendered with.
And that is why I use the above script. I have teste both your suggestion and the above script and the result in frame rate is identical.
But thank you very much for your time and input.