private static void CreateMeshForAnimations(Mesh sourceMesh, TEXCOORD boneIdChannel, TEXCOORD boneWeightChannel, int bonesPerVertex, string path) { Mesh mesh = CreateMeshWithExtraData(sourceMesh, boneIdChannel, boneWeightChannel, bonesPerVertex); mesh.UploadMeshData(true); string assetPath = FileUtil.GetProjectRelativePath(path); AssetDatabase.CreateAsset(mesh, assetPath); AssetDatabase.SaveAssets(); }
private static Mesh CreateMeshWithExtraData(Mesh sourceMesh, TEXCOORD boneIdsUVChanel, TEXCOORD boneWeightsUVChanel, int bonesPerVertex) { Mesh mesh = Instantiate(sourceMesh); //Add bone IDs and weights as texture data { List <Vector4> boneIdsData = new List <Vector4>(); List <Vector4> boneWeightsData = new List <Vector4>(); for (int i = 0; i != mesh.vertexCount; ++i) { BoneWeight weight = mesh.boneWeights[i]; Vector4 boneIds; boneIds.x = weight.boneIndex0; boneIds.y = weight.boneIndex1; boneIds.z = weight.boneIndex2; boneIds.w = weight.boneIndex3; boneIdsData.Add(boneIds); Vector4 boneWeights; boneWeights.x = weight.weight0; boneWeights.y = weight.weight1; boneWeights.z = weight.weight2; boneWeights.w = weight.weight3; if (bonesPerVertex == 3) { float rate = 1.0f / (weight.boneIndex0 + weight.boneIndex1 + weight.boneIndex2); boneWeights.x = boneWeights.x * rate; boneWeights.y = boneWeights.y * rate; boneWeights.z = boneWeights.z * rate; boneWeights.w = -0.1f; } else if (bonesPerVertex == 2) { float rate = 1.0f / (weight.boneIndex0 + weight.boneIndex1); boneWeights.x = boneWeights.x * rate; boneWeights.y = boneWeights.y * rate; boneWeights.z = -0.1f; boneWeights.w = -0.1f; } else if (bonesPerVertex == 1) { boneWeights.x = 1.0f; boneWeights.y = -0.1f; boneWeights.z = -0.1f; boneWeights.w = -0.1f; } boneWeightsData.Add(boneWeights); } mesh.SetUVs((int)boneIdsUVChanel, boneIdsData); mesh.SetUVs((int)boneWeightsUVChanel, boneWeightsData); } return(mesh); }
private void OnGUI() { ScriptableObject target = this; SerializedObject so = new SerializedObject(target); GUI.skin.label.richText = true; GUILayout.BeginHorizontal(); { GUILayout.FlexibleSpace(); } GUILayout.EndHorizontal(); EditorGUILayout.Separator(); GUILayout.BeginVertical(); { EditorGUILayout.LabelField("Generate GPU Animation Texture", EditorStyles.largeLabel); EditorGUILayout.Separator(); GameObject prefab = EditorGUILayout.ObjectField("Asset to Evaluate", _evaluatedObject, typeof(GameObject), true) as GameObject; if (prefab != _evaluatedObject) { _evaluatedObject = prefab; _skinnedMeshes = prefab != null?prefab.GetComponentsInChildren <SkinnedMeshRenderer>() : new SkinnedMeshRenderer[0]; _skinnedMeshIndex = 0; _boneNames = _skinnedMeshIndex < _skinnedMeshes.Length ? GetBoneNames(_skinnedMeshes[_skinnedMeshIndex]) : null; _exposedBones = new List <int>(); _useAnimator = prefab != null && GameObjectUtils.GetComponent <Animator>(_evaluatedObject, true) != null; } if (_evaluatedObject != null && _skinnedMeshes != null && _skinnedMeshes.Length > 0) { //Draw Skinned Mesh Popup { string[] skinnedMeshes = new string[_skinnedMeshes.Length]; for (int i = 0; i < skinnedMeshes.Length; i++) { skinnedMeshes[i] = _skinnedMeshes[i].gameObject.name; } int skinnedMeshIndex = EditorGUILayout.Popup("Skinned Mesh", _skinnedMeshIndex, skinnedMeshes); if (skinnedMeshIndex != _skinnedMeshIndex) { _skinnedMeshIndex = skinnedMeshIndex; _boneNames = GetBoneNames(_skinnedMeshes[_skinnedMeshIndex]); _exposedBones = new List <int>(); } } //Draw option for sampling with animator if object has one { Animator animator = GameObjectUtils.GetComponent <Animator>(_evaluatedObject, true); if (animator != null) { _useAnimator = EditorGUILayout.Toggle("Use Animator", _useAnimator); } else { _useAnimator = false; } } //If not usign animator, draw array for animations instead if (!_useAnimator) { //Draw list showing animation clip, SerializedProperty animationsProperty = so.FindProperty("_animations"); EditorGUILayout.PropertyField(animationsProperty, true); so.ApplyModifiedProperties(); } //Draw options for Exposed bones EditorGUILayout.BeginHorizontal(); { EditorGUILayout.LabelField(new GUIContent("Exposed Bones")); string exposedBones = _exposedBones.Count == 0 ? "None" : _boneNames[_exposedBones[0]]; for (int i = 1; i < _exposedBones.Count; i++) { exposedBones += ", " + _boneNames[_exposedBones[i]]; } if (EditorGUILayout.DropdownButton(new GUIContent(exposedBones), FocusType.Keyboard)) { GenericMenu menu = new GenericMenu(); for (int i = 0; i < _boneNames.Length; i++) { menu.AddItem(new GUIContent(_boneNames[i]), _exposedBones.Contains(i), OnClickExposedBone, i); } menu.ShowAsContext(); } } EditorGUILayout.EndHorizontal(); if (_working) { EditorGUILayout.LabelField("Generating Animation Texture", EditorStyles.helpBox); } else if (_skinnedMeshes != null && (_useAnimator || (_animations != null && _animations.Length > 0))) { if (GUILayout.Button("Generate")) { string path = EditorUtility.SaveFilePanelInProject("Save Animation Texture", Path.GetFileNameWithoutExtension(""), "bytes", "Please enter a file name to save the animation texture to"); if (!string.IsNullOrEmpty(path)) { Run(BakeAnimationTexture(path)); } } } } } GUILayout.EndVertical(); EditorGUILayout.Separator(); EditorGUILayout.Separator(); EditorGUILayout.Separator(); GUILayout.BeginVertical(); { EditorGUILayout.LabelField("Generate GPU Animated Mesh", EditorStyles.largeLabel); EditorGUILayout.Separator(); _mesh = EditorGUILayout.ObjectField("Mesh", _mesh, typeof(Mesh), true) as Mesh; _boneIdChanel = (TEXCOORD)EditorGUILayout.EnumPopup("Bone IDs UV Channel", _boneIdChanel); _boneWeightChannel = (TEXCOORD)EditorGUILayout.EnumPopup("Bone Weights UV Channel", _boneWeightChannel); _numBonesPerVertex = EditorGUILayout.IntSlider(new GUIContent("Bones Per Vertex"), _numBonesPerVertex, 1, 4); if (_mesh != null) { if (GUILayout.Button("Generate Animated Texture Ready Mesh")) { string path = EditorUtility.SaveFilePanel("Save Mesh Asset", "Assets/", name, "asset"); if (!string.IsNullOrEmpty(path)) { CreateMeshForAnimations(_mesh, _boneIdChanel, _boneWeightChannel, _numBonesPerVertex, path); } } } } GUILayout.EndVertical(); }