/racer/Assets/~AlternatePhysicsModel/Scripts/Skidmarks.cs

https://bitbucket.org/marvin0038/racer · C# · 154 lines · 119 code · 22 blank · 13 comment · 20 complexity · 0d11ed078b6c422e475c5bf8b54d3baa MD5 · raw file

  1. using UnityEngine;
  2. using System.Collections;
  3. public class Skidmarks : MonoBehaviour {
  4. /////////
  5. // Skidmarks.cs
  6. //
  7. // This script controlles the skidmarks for the car. It registers the position, normal etc. of all the small sections of
  8. // the skidmarks that combined makes up the entire skidmark mesh.
  9. // A new mesh is auto generated whenever the skidmarks change.
  10. public int maxMarks = 1024; // Maximum number of marks total handled by one instance of the script.
  11. public float markWidth = 0.275f; // The width of the skidmarks. Should match the width of the wheel that it is used for. In meters.
  12. public float groundOffset = 0.02f; // The distance the skidmarks is places above the surface it is placed upon. In meters.
  13. public float minDistance = 0.1f; // The minimum distance between two marks places next to each other.
  14. int indexShift;
  15. int numMarks = 0;
  16. // Variables for each mark created. Needed to generate the correct mesh.
  17. class MarkSection{
  18. public Vector3 pos = Vector3.zero;
  19. public Vector3 normal = Vector3.zero;
  20. public Vector4 tangent = Vector4.zero;
  21. public Vector3 posl = Vector3.zero;
  22. public Vector3 posr = Vector3.zero;
  23. public float intensity = 0.0f;
  24. public int lastIndex = 0;
  25. };
  26. private MarkSection[] skidmarks;
  27. private bool updated = false;
  28. // Initiallizes the array holding the skidmark sections.
  29. void Awake()
  30. {
  31. skidmarks = new MarkSection[maxMarks];
  32. for (int i = 0; i < maxMarks; i++)
  33. skidmarks[i] = new MarkSection();
  34. if (((MeshFilter) GetComponent (typeof(MeshFilter))).mesh == null)
  35. ((MeshFilter) GetComponent (typeof(MeshFilter))).mesh = new Mesh();
  36. }
  37. // Function called by the wheels that is skidding. Gathers all the information needed to
  38. // create the mesh later. Sets the intensity of the skidmark section b setting the alpha
  39. // of the vertex color.
  40. public int AddSkidMark(Vector3 pos, Vector3 normal, float intensity, int lastIndex)
  41. {
  42. if(intensity > 1)
  43. intensity = 1.0f;
  44. if(intensity < 0)
  45. return -1;
  46. MarkSection curr = skidmarks[numMarks % maxMarks];
  47. curr.pos = pos + normal * groundOffset;
  48. curr.normal = normal;
  49. curr.intensity = intensity;
  50. curr.lastIndex = lastIndex;
  51. if(lastIndex != -1)
  52. {
  53. MarkSection last = skidmarks[lastIndex % maxMarks];
  54. Vector3 dir = (curr.pos - last.pos);
  55. Vector3 xDir = Vector3.Cross(dir,normal).normalized;
  56. curr.posl = curr.pos + xDir * markWidth * 0.5f;
  57. curr.posr = curr.pos - xDir * markWidth * 0.5f;
  58. curr.tangent = new Vector4(xDir.x, xDir.y, xDir.z, 1);
  59. if(last.lastIndex == -1)
  60. {
  61. last.tangent = curr.tangent;
  62. last.posl = curr.pos + xDir * markWidth * 0.5f;
  63. last.posr = curr.pos - xDir * markWidth * 0.5f;
  64. }
  65. }
  66. numMarks++;
  67. updated = true;
  68. return numMarks -1;
  69. }
  70. // If the mesh needs to be updated, i.e. a new section has been added,
  71. // the current mesh is removed, and a new mesh for the skidmarks is generated.
  72. void LateUpdate()
  73. {
  74. if(!updated)
  75. {
  76. return;
  77. }
  78. updated = false;
  79. Mesh mesh = ((MeshFilter) GetComponent (typeof(MeshFilter))).mesh;
  80. mesh.Clear();
  81. int segmentCount = 0;
  82. for(int j = 0; j < numMarks && j < maxMarks; j++)
  83. if(skidmarks[j].lastIndex != -1 && skidmarks[j].lastIndex > numMarks - maxMarks)
  84. segmentCount++;
  85. Vector3[] vertices = new Vector3[segmentCount * 4];
  86. Vector3[] normals = new Vector3[segmentCount * 4];
  87. Vector4[] tangents = new Vector4[segmentCount * 4];
  88. Color[] colors = new Color[segmentCount * 4];
  89. Vector2[] uvs = new Vector2[segmentCount * 4];
  90. int[] triangles = new int[segmentCount * 6];
  91. segmentCount = 0;
  92. for(int i = 0; i < numMarks && i < maxMarks; i++)
  93. if(skidmarks[i].lastIndex != -1 && skidmarks[i].lastIndex > numMarks - maxMarks)
  94. {
  95. MarkSection curr = skidmarks[i];
  96. MarkSection last = skidmarks[curr.lastIndex % maxMarks];
  97. vertices[segmentCount * 4 + 0] = last.posl;
  98. vertices[segmentCount * 4 + 1] = last.posr;
  99. vertices[segmentCount * 4 + 2] = curr.posl;
  100. vertices[segmentCount * 4 + 3] = curr.posr;
  101. normals[segmentCount * 4 + 0] = last.normal;
  102. normals[segmentCount * 4 + 1] = last.normal;
  103. normals[segmentCount * 4 + 2] = curr.normal;
  104. normals[segmentCount * 4 + 3] = curr.normal;
  105. tangents[segmentCount * 4 + 0] = last.tangent;
  106. tangents[segmentCount * 4 + 1] = last.tangent;
  107. tangents[segmentCount * 4 + 2] = curr.tangent;
  108. tangents[segmentCount * 4 + 3] = curr.tangent;
  109. colors[segmentCount * 4 + 0]=new Color(0, 0, 0, last.intensity);
  110. colors[segmentCount * 4 + 1]=new Color(0, 0, 0, last.intensity);
  111. colors[segmentCount * 4 + 2]=new Color(0, 0, 0, curr.intensity);
  112. colors[segmentCount * 4 + 3]=new Color(0, 0, 0, curr.intensity);
  113. uvs[segmentCount * 4 + 0] = new Vector2(0, 0);
  114. uvs[segmentCount * 4 + 1] = new Vector2(1, 0);
  115. uvs[segmentCount * 4 + 2] = new Vector2(0, 1);
  116. uvs[segmentCount * 4 + 3] = new Vector2(1, 1);
  117. triangles[segmentCount * 6 + 0] = segmentCount * 4 + 0;
  118. triangles[segmentCount * 6 + 2] = segmentCount * 4 + 1;
  119. triangles[segmentCount * 6 + 1] = segmentCount * 4 + 2;
  120. triangles[segmentCount * 6 + 3] = segmentCount * 4 + 2;
  121. triangles[segmentCount * 6 + 5] = segmentCount * 4 + 1;
  122. triangles[segmentCount * 6 + 4] = segmentCount * 4 + 3;
  123. segmentCount++;
  124. }
  125. mesh.vertices=vertices;
  126. mesh.normals=normals;
  127. mesh.tangents=tangents;
  128. mesh.triangles=triangles;
  129. mesh.colors=colors;
  130. mesh.uv=uvs;
  131. }
  132. }