public static void SetFromBoneWeight(this EditableBoneWeight editableBoneWeight, BoneWeight boneWeight) { editableBoneWeight.Clamp(4, false); while (editableBoneWeight.Count < 4) { editableBoneWeight.AddChannel(0, 0f, false); } for (var i = 0; i < 4; ++i) { var weight = boneWeight.GetWeight(i); editableBoneWeight[i].boneIndex = boneWeight.GetBoneIndex(i); editableBoneWeight[i].weight = weight; editableBoneWeight[i].enabled = weight > 0f; } }
protected void AssertBoneWeightContainsChannels(BoneWeight expected, BoneWeight actual) { var m_BoneWeightDataList = new List <BoneWeightData>(); for (var i = 0; i < 4; ++i) { m_BoneWeightDataList.Add(new BoneWeightData() { boneIndex = expected.GetBoneIndex(i), weight = expected.GetWeight(i) }); } for (var i = 0; i < 4; ++i) { Assert.IsTrue(m_BoneWeightDataList.Contains(new BoneWeightData() { boneIndex = actual.GetBoneIndex(i), weight = actual.GetWeight(i) }), "BoneWeight incorrect channel " + i + " with boneIndex " + actual.GetBoneIndex(i) + " and weight " + actual.GetWeight(i)); } }
public void OnSceneGUI(SceneView sceneView) { if (skin != null && isPainting) { HandleUtility.AddDefaultControl(GUIUtility.GetControlID(FocusType.Passive)); if (mesh == null || recalculateMesh) { mesh = new Mesh(); skin.BakeMesh(mesh); mesh.normals = skin.sharedMesh.normals; mesh.bindposes = skin.sharedMesh.bindposes; mesh.bounds = skin.sharedMesh.bounds; mesh.uv = skin.sharedMesh.uv; mesh.uv2 = skin.sharedMesh.uv2; mesh.boneWeights = skin.sharedMesh.boneWeights; mesh.tangents = skin.sharedMesh.tangents; mesh.GetVertices(vertices); for (int i = 0; i < mesh.vertexCount; i++) { vertices[i] = new Vector3( vertices[i].x * skin.transform.lossyScale.x, vertices[i].y * skin.transform.lossyScale.y, vertices[i].z * skin.transform.lossyScale.z); } mesh.SetVertices(vertices); recalculateMesh = false; } else { mesh.boneWeights = skin.sharedMesh.boneWeights; } CalculateVertexColors(skin.bones, bones[boneIndex]); List <BoneWeight> weights = mesh.boneWeights.ToList(); Event current = Event.current; Graphics.DrawMeshNow(mesh, skin.transform.localToWorldMatrix); for (int b = 0; b < bones.Length; b++) { if (bones[b] == bones[boneIndex]) { Handles.color = Color.yellow; } else { Handles.color = Color.gray; } Handles.DrawLine(bones[b].transform.position, bones[b].Head); } Handles.color = Color.red; mpos = HandleUtility.GUIPointToWorldRay(current.mousePosition).origin; mpos = new Vector3(mpos.x, mpos.y); Handles.DrawWireDisc(mpos, Vector3.forward, brushSize); if (isPainting) { if (current.type == EventType.ScrollWheel && current.modifiers == EventModifiers.Control) { brushSize = Mathf.Clamp(brushSize + (float)System.Math.Round(current.delta.y / 30, 2), 0, float.MaxValue); Repaint(); current.Use(); } else if (current.type == EventType.MouseDown && current.button == 0) { isDrawing = true; wasDrawing = false; } else if (current.type == EventType.MouseUp && current.button == 0) { if (isDrawing) { wasDrawing = true; recalculateMesh = true; } isDrawing = false; } else if (current.type == EventType.MouseDrag && isDrawing && current.button == 0) { w = weight * ((mode == PaintingMode.Subtract) ? -1 : 1); for (int i = 0; i < mesh.vertices.Length; i++) { v = mesh.vertices[i]; d = (v - skin.gameObject.transform.InverseTransformPoint(mpos)).magnitude; if (d <= brushSize) { bw = weights[i]; vw = bw.GetWeight(boneIndex); vw = Mathf.Clamp(vw + (1 - d / brushSize) * w, 0, 1); bw = bw.SetWeight(boneIndex, vw); weights[i] = bw.Clone(); } } skin.sharedMesh.boneWeights = weights.ToArray(); } } sceneView.Repaint(); } }
public void OnSceneGUI(SceneView sceneView) { if (skin != null && isPainting) { HandleUtility.AddDefaultControl(GUIUtility.GetControlID(FocusType.Passive)); Mesh m = skin.sharedMesh.Clone(); m.colors = CalculateVertexColors(skin.bones, m, skin.bones[bone].GetComponent <Bone>()); List <BoneWeight> weights = m.boneWeights.ToList(); Event current = Event.current; Graphics.DrawMeshNow(m, skin.transform.position, skin.transform.rotation); Bone bn = skin.bones[bone].GetComponent <Bone>(); foreach (Bone b in skin.GetComponentsInChildren <Bone>()) { if (bn == b) { Handles.color = Color.yellow; } else { Handles.color = Color.gray; } Handles.DrawLine(b.transform.position, b.Head); } Handles.color = Color.red; Vector3 mpos = HandleUtility.GUIPointToWorldRay(current.mousePosition).origin; mpos = new Vector3(mpos.x, mpos.y); Handles.DrawWireDisc(mpos, Vector3.forward, brushSize); if (isPainting) { if (current.type == EventType.scrollWheel && current.modifiers == EventModifiers.Control) { brushSize = Mathf.Clamp(brushSize + (float)System.Math.Round(current.delta.y / 30, 2), 0, float.MaxValue); Repaint(); current.Use(); } else if (current.type == EventType.mouseDown && current.button == 0) { isDrawing = true; } else if (current.type == EventType.mouseUp && current.button == 0) { isDrawing = false; } else if (current.type == EventType.mouseDrag && isDrawing && current.button == 0) { float w = weight * ((mode == PaintingMode.Subtract) ? -1 : 1); for (int i = 0; i < m.vertices.Length; i++) { Vector3 v = m.vertices[i]; float d = (v - skin.gameObject.transform.InverseTransformPoint(mpos)).magnitude; if (d <= brushSize) { BoneWeight bw = weights[i]; float vw = bw.GetWeight(bn.index); vw = Mathf.Clamp(vw + (1 - d / brushSize) * w, 0, 1); bw = bw.SetWeight(bn.index, vw); weights[i] = bw.Clone(); } } skin.sharedMesh.boneWeights = weights.ToArray(); EditorUtility.SetDirty(skin.gameObject); if (PrefabUtility.GetPrefabType(skin.gameObject) != PrefabType.None) { AssetDatabase.SaveAssets(); } } } sceneView.Repaint(); } }
void GenerateSkinning() { SkinTools t = target as SkinTools; SkinToolsData data = t.Data; bool referenceExist = data.ReferenceSMR != null; Vector3[] rVertices = data.SourceGeometryMF.sharedMesh.vertices; Vector3[] rNormals = data.SourceGeometryMF.sharedMesh.normals; Vector3[] rWorldVertices = new Vector3[rVertices.Length]; Vector2[] rMapVertices = data.SourceGeometryMF.sharedMesh.uv; Matrix4x4 smLTW = data.SourceGeometryMF.transform.localToWorldMatrix; Matrix4x4 tWTL = t.transform.worldToLocalMatrix; for (int v = 0; v < rVertices.Length; v++) { rWorldVertices[v] = smLTW.MultiplyPoint3x4(rVertices[v]); rVertices[v] = tWTL.MultiplyPoint3x4(rWorldVertices[v]); rNormals[v] = smLTW.MultiplyVector(rNormals[v]); rNormals[v] = tWTL.MultiplyVector(rNormals[v]); } data.ResultMesh = Instantiate(data.SourceGeometryMF.sharedMesh) as Mesh; string[] splittedPath = data.OutputMeshPath.Split("/.".ToCharArray()); string meshName = splittedPath[splittedPath.Length - 2]; data.ResultMesh.name = meshName; data.ResultMesh.vertices = rVertices; data.ResultMesh.normals = rNormals; data.ResultMesh.RecalculateBounds(); data.resultSMR.localBounds = new Bounds(data.ResultMesh.bounds.center, data.ResultMesh.bounds.size * 2); SourceSMRCollider _collider = null; SourceSMRCollider _icollider = null; BoneWeight[] existingWeights = null; Transform[] sourceBones = null; int[] sourceSMRTris = null; Ray[] frays = null; bool[] excludedTriangles = null; if (referenceExist) { _collider = new SourceSMRCollider(data.ReferenceSMR, false); _icollider = new SourceSMRCollider(data.ReferenceSMR, true); existingWeights = data.ReferenceSMR.sharedMesh.boneWeights; sourceBones = data.ReferenceSMR.bones; sourceSMRTris = data.ReferenceSMR.sharedMesh.triangles; excludedTriangles = new bool[data.ReferenceSMR.sharedMesh.triangles.Length / 3]; if (data.ReferenceSMRGeometry != null && data.ReferenceSMRGeometry.IsValid) { excludedTriangles = data.ReferenceSMRGeometry.ExcludedTris; } if (data.BakingQuality == 0) { frays = new Ray[ResourceHolder.Rays362.Length]; for (int i = 0; i < frays.Length; i++) { frays[i] = new Ray(Vector3.zero, ResourceHolder.Rays362[i]); } } else if (data.BakingQuality == 1) { frays = new Ray[ResourceHolder.Rays642.Length]; for (int i = 0; i < frays.Length; i++) { frays[i] = new Ray(Vector3.zero, ResourceHolder.Rays642[i]); } } else if (data.BakingQuality == 2) { frays = new Ray[ResourceHolder.Rays1002.Length]; for (int i = 0; i < frays.Length; i++) { frays[i] = new Ray(Vector3.zero, ResourceHolder.Rays1002[i]); } } } ExtBoneWeight[] ebws = new ExtBoneWeight[rWorldVertices.Length]; List <Transform> newBonesList = new List <Transform>(); for (int b = 0; b < data.MapBones.Count; b++) { newBonesList.Add(data.MapBones[b].Tr); } EditorUtility.DisplayProgressBar("Bake", "Baking vertices", 0); int progressPercent = 0; for (int v = 0; v < rWorldVertices.Length; v++) { ebws[v] = new ExtBoneWeight( ); if (data.SourceGeometry.HasUV0) { Vector2 uv = rMapVertices[v]; for (int b = 0; b < data.MapBones.Count; b++) { float val = data.MapBones[b].Map.GetPixelBilinear(uv.x, uv.y).grayscale; ebws[v].AddMask(data.MapBones[b].Tr, val); } } if (referenceExist) { RaycastHit hit = GetNearestHit(frays, _collider._Collider, _icollider._Collider, rWorldVertices[v], excludedTriangles); BoneWeight bwA = existingWeights [sourceSMRTris[hit.triangleIndex * 3]]; BoneWeight bwB = existingWeights [sourceSMRTris[hit.triangleIndex * 3 + 1]]; BoneWeight bwC = existingWeights [sourceSMRTris[hit.triangleIndex * 3 + 2]]; for (int i = 0; i < 4; i++) { Transform nbA = sourceBones[bwA.GetBoneIdx(i)]; Transform nbB = sourceBones[bwB.GetBoneIdx(i)]; Transform nbC = sourceBones[bwC.GetBoneIdx(i)]; if (!data.ReferenceSMRBones[nbA].Excluded) { if (!newBonesList.Contains(nbA)) { newBonesList.Add(nbA); } ebws[v].Add(nbA, bwA.GetWeight(i) * hit.barycentricCoordinate.x, 0); } if (!data.ReferenceSMRBones[nbB].Excluded) { if (!newBonesList.Contains(nbB)) { newBonesList.Add(nbB); } ebws[v].Add(nbB, bwB.GetWeight(i) * hit.barycentricCoordinate.y, 0); } if (!data.ReferenceSMRBones[nbC].Excluded) { if (!newBonesList.Contains(nbC)) { newBonesList.Add(nbC); } ebws[v].Add(nbC, bwC.GetWeight(i) * hit.barycentricCoordinate.z, 0); } } } float progress = v / (float)rWorldVertices.Length; int percent = Mathf.FloorToInt(progress * 100); if (progressPercent != percent) { progressPercent = percent; string progressBarName = string.Format("Bake {0}", data.ResultMesh.name); string progressInfo = string.Format("baking vertices {0} of {1} with {2} quality ", v, rWorldVertices.Length, data.BakingQualityNames[data.BakingQuality]); EditorUtility.DisplayProgressBar(progressBarName, progressInfo, progress); } } EditorUtility.ClearProgressBar(); BoneWeight[] newweights = new BoneWeight[rWorldVertices.Length]; Transform[] newBonesArray = newBonesList.ToArray(); for (int w = 0; w < ebws.Length; w++) { ebws[w].FillIndeces(newBonesArray); newweights[w] = ebws[w].GetClampedBW(); } data.resultSMR.bones = newBonesArray; Matrix4x4[] bindBones = new Matrix4x4[newBonesArray.Length]; for (int b = 0; b < newBonesArray.Length; b++) { bindBones[b] = newBonesArray[b].worldToLocalMatrix * t.transform.localToWorldMatrix; } data.ResultMesh.bindposes = bindBones; data.ResultMesh.boneWeights = newweights; if (referenceExist) { _collider.Destroy(); _icollider.Destroy(); } AssetDatabase.DeleteAsset(data.OutputMeshPath); AssetDatabase.CreateAsset(data.ResultMesh, data.OutputMeshPath); AssetDatabase.SaveAssets(); data.ResultMesh = AssetDatabase.LoadAssetAtPath(data.OutputMeshPath, typeof(Mesh)) as Mesh; data.resultSMR.sharedMesh = data.ResultMesh; data.UpdateResultInfo(); data.ApplyResultVisual(); }
public static BoneWeight Lerp(BoneWeight a, BoneWeight b, float mix) { if (mix <= 0f) { return(a); } if (mix >= 1f) { return(b); } a.weight0 *= 1f - mix; a.weight1 *= 1f - mix; a.weight2 *= 1f - mix; a.weight3 *= 1f - mix; b.weight0 *= mix; b.weight1 *= mix; b.weight2 *= mix; b.weight3 *= mix; BoneWeight result = default(BoneWeight); int num = 0; int num2 = 0; if (a.GetWeight(num) > b.GetWeight(num2)) { result.weight0 = a.GetWeight(num); result.boneIndex0 = a.GetBoneIndex(num); num++; } else { result.weight0 = b.GetWeight(num2); result.boneIndex0 = b.GetBoneIndex(num2); num2++; } if (a.GetWeight(num) > b.GetWeight(num2)) { result.weight1 = a.GetWeight(num); result.boneIndex1 = a.GetBoneIndex(num); num++; } else { result.weight1 = b.GetWeight(num2); result.boneIndex1 = b.GetBoneIndex(num2); num2++; } if (a.GetWeight(num) > b.GetWeight(num2)) { result.weight2 = a.GetWeight(num); result.boneIndex2 = a.GetBoneIndex(num); num++; } else { result.weight2 = b.GetWeight(num2); result.boneIndex2 = b.GetBoneIndex(num2); num2++; } if (a.GetWeight(num) > b.GetWeight(num2)) { result.weight3 = a.GetWeight(num); result.boneIndex3 = a.GetBoneIndex(num); num++; } else { result.weight3 = b.GetWeight(num2); result.boneIndex3 = b.GetBoneIndex(num2); num2++; } float num3 = result.weight0 + result.weight1 + result.weight2 + result.weight3; if (num3 != 0f) { result.weight0 /= num3; result.weight1 /= num3; result.weight2 /= num3; result.weight3 /= num3; } return(result); }