DMeville

Untitled

Jun 19th, 2019
168
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.54 KB | None | 0 0
  1. using UnityEngine;
  2. #if UNITY_EDITOR
  3. using UnityEditor;
  4. #endif
  5. using System.Collections;
  6. using System.Collections.Generic;
  7.  
  8. [RequireComponent(typeof(MeshFilter))]
  9. public class SoftNormalsToVertexColor:MonoBehaviour {
  10.  
  11. public enum Method { Simple, AngularDeviation };
  12.  
  13. public Method method = Method.AngularDeviation;
  14. public bool generateOnAwake = false;
  15. public bool generateNow = false;
  16.  
  17. void OnDrawGizmos() {
  18. if(generateNow) {
  19. generateNow = false;
  20. TryGenerate();
  21. }
  22. }
  23.  
  24. void Awake() {
  25. if(generateOnAwake)
  26. TryGenerate();
  27. }
  28.  
  29. void TryGenerate() {
  30. MeshFilter mf = GetComponent<MeshFilter>();
  31. if(mf == null) {
  32. Debug.LogError("MeshFilter missing on the vertex color generator", gameObject);
  33. return;
  34. }
  35. if(mf.sharedMesh == null) {
  36. Debug.LogError("Assign a mesh to the MeshFilter before generating vertex colors", gameObject);
  37. return;
  38. }
  39. Generate(mf.sharedMesh);
  40. Debug.Log("Vertex colors generated", gameObject);
  41. }
  42.  
  43. void Generate(Mesh m) {
  44.  
  45. Vector3[] n = m.normals;
  46. Vector3[] v = m.vertices;
  47. Color[] colors = new Color[n.Length];
  48. List<List<int>> groups = new List<List<int>>();
  49.  
  50. for(int i = 0; i < v.Length; i++) { // Group verts at the same location
  51. bool added = false;
  52. foreach(List<int> group in groups) { // Add to exsisting group if possible
  53. if(v[group[0]] == v[i]) {
  54. group.Add(i);
  55. added = true;
  56. break;
  57. }
  58. }
  59. if(!added) { // Create new group if necessary
  60. List<int> newList = new List<int>();
  61. newList.Add(i);
  62. groups.Add(newList);
  63. }
  64. }
  65.  
  66. foreach(List<int> group in groups) { // Calculate soft normals
  67. Vector3 avgNrm = Vector3.zero;
  68. foreach(int i in group) { // TODO: This can actually be improved. Averaging will not give the best outline.
  69. avgNrm += n[i];
  70. }
  71. avgNrm.Normalize(); // Average normal done
  72. if(method == Method.AngularDeviation) {
  73. float avgDot = 0f; // Calculate deviation to alter length
  74. foreach(int i in group) {
  75. avgDot += Vector3.Dot(n[i], avgNrm);
  76. }
  77. avgDot /= group.Count;
  78. float angDeviation = Mathf.Acos(avgDot) * Mathf.Rad2Deg;
  79. float aAng = 180f - angDeviation - 90;
  80. float lMult = 0.5f / Mathf.Sin(aAng * Mathf.Deg2Rad); // 0.5f looks better empirically, but mathematically it should be 1f
  81. avgNrm *= lMult;
  82. }
  83.  
  84. foreach(int i in group) {
  85.  
  86. //colors[i] = new Color(avgNrm.x, avgNrm.y, avgNrm.z); // Save normals as colors
  87. Vector3 remappedNormal = ((avgNrm.normalized + Vector3.one) / 2f); //[-1, 1] -> [0,1]; Loses precision, but fbx exporter seems to clamp colors [0,1] so our normals get messed up
  88. colors[i] = new Color(remappedNormal.x, remappedNormal.y, remappedNormal.z);
  89. }
  90. }
  91.  
  92. m.colors = colors; // Assign as vertex colors
  93. Debug.Log("v: " + m.vertices.Length + " : vc: " + colors.Length);
  94. #if UNITY_EDITOR
  95. EditorUtility.SetDirty(this);
  96. SceneView.RepaintAll();
  97. #endif
  98.  
  99. }
  100.  
  101.  
  102. }
Advertisement
Add Comment
Please, Sign In to add comment