220 lines
7.0 KiB
C#
220 lines
7.0 KiB
C#
//----------------------------------------------
|
|
// Realistic Car Controller
|
|
//
|
|
// Copyright © 2014 - 2023 BoneCracker Games
|
|
// https://www.bonecrackergames.com
|
|
// Buğra Özdoğanlar
|
|
//
|
|
//----------------------------------------------
|
|
|
|
using UnityEngine;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
|
|
/// <summary>
|
|
/// Skidmarks Manager for RCC.
|
|
/// </summary>
|
|
[AddComponentMenu("BoneCracker Games/Realistic Car Controller/Misc/RCC Skidmarks")]
|
|
public class RCC_Skidmarks : MonoBehaviour {
|
|
|
|
private MeshFilter meshFilter; // Mesh filter.
|
|
private Mesh mesh; // Mesh.
|
|
|
|
public int maxMarks = 1024; // Maximum number of marks total handled by one instance of the script.
|
|
public float groundOffset = 0.02f; // The distance the skidmarks is places above the surface it is placed upon. In meters.
|
|
public float minDistance = 0.1f; // The minimum distance between two marks places next to each other.
|
|
|
|
private int numMarks = 0;
|
|
|
|
/// <summary>
|
|
/// Variables for each mark created. Needed to generate the correct mesh.
|
|
/// </summary>
|
|
public class MarkSection {
|
|
|
|
public Vector3 pos = Vector3.zero;
|
|
public Vector3 normal = Vector3.zero;
|
|
public Vector4 tangent = Vector4.zero;
|
|
public Vector3 posl = Vector3.zero;
|
|
public Vector3 posr = Vector3.zero;
|
|
public float intensity = 0.0f;
|
|
public int lastIndex = 0;
|
|
|
|
}
|
|
|
|
public MarkSection[] skidmarks;
|
|
|
|
private bool updated = false;
|
|
|
|
/// <summary>
|
|
/// Initiallizes the array holding the skidmark sections.
|
|
/// </summary>
|
|
private void Awake() {
|
|
|
|
transform.position = Vector3.zero;
|
|
|
|
skidmarks = new MarkSection[maxMarks];
|
|
|
|
for (int i = 0; i < maxMarks; i++)
|
|
skidmarks[i] = new MarkSection();
|
|
|
|
meshFilter = GetComponent<MeshFilter>();
|
|
mesh = meshFilter.mesh;
|
|
|
|
}
|
|
|
|
// Function called by the wheels that is skidding. Gathers all the information needed to
|
|
// create the mesh later. Sets the intensity of the skidmark section b setting the alpha
|
|
// of the vertex color.
|
|
public int AddSkidMark(Vector3 pos, Vector3 normal, float intensity, float width, int lastIndex) {
|
|
|
|
if (intensity > 1f)
|
|
intensity = 1f;
|
|
if (intensity < 0f)
|
|
return -1;
|
|
|
|
if (pos == Vector3.zero)
|
|
return -1;
|
|
if (normal == Vector3.zero)
|
|
return -1;
|
|
|
|
if (lastIndex > 0) {
|
|
|
|
float sqrDistance = (pos - skidmarks[lastIndex % maxMarks].pos).sqrMagnitude;
|
|
|
|
if (sqrDistance < minDistance)
|
|
return lastIndex;
|
|
|
|
}
|
|
|
|
MarkSection curr = skidmarks[numMarks % maxMarks];
|
|
curr.pos = pos + normal * groundOffset;
|
|
curr.normal = normal;
|
|
curr.intensity = intensity;
|
|
curr.lastIndex = lastIndex;
|
|
|
|
if (lastIndex != -1) {
|
|
|
|
MarkSection last = skidmarks[lastIndex % maxMarks];
|
|
Vector3 dir = (curr.pos - last.pos);
|
|
Vector3 xDir = Vector3.Cross(dir, normal).normalized;
|
|
|
|
curr.posl = curr.pos + xDir * width * 0.5f;
|
|
curr.posr = curr.pos - xDir * width * 0.5f;
|
|
curr.tangent = new Vector4(xDir.x, xDir.y, xDir.z, 1);
|
|
|
|
if (last.lastIndex == -1) {
|
|
|
|
last.tangent = curr.tangent;
|
|
last.posl = curr.pos + xDir * width * 0.5f;
|
|
last.posr = curr.pos - xDir * width * 0.5f;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
numMarks++;
|
|
updated = true;
|
|
|
|
return numMarks - 1;
|
|
|
|
}
|
|
|
|
// If the mesh needs to be updated, i.e. a new section has been added,
|
|
// the current mesh is removed, and a new mesh for the skidmarks is generated.
|
|
private void LateUpdate() {
|
|
|
|
if (!updated)
|
|
return;
|
|
|
|
updated = false;
|
|
|
|
mesh.Clear();
|
|
|
|
int segmentCount = 0;
|
|
|
|
for (int j = 0; j < numMarks && j < maxMarks; j++) {
|
|
|
|
if (skidmarks[j].lastIndex != -1 && skidmarks[j].lastIndex > numMarks - maxMarks)
|
|
segmentCount++;
|
|
|
|
}
|
|
|
|
Vector3[] vertices = new Vector3[segmentCount * 4];
|
|
Vector3[] normals = new Vector3[segmentCount * 4];
|
|
Vector4[] tangents = new Vector4[segmentCount * 4];
|
|
Color[] colors = new Color[segmentCount * 4];
|
|
Vector2[] uvs = new Vector2[segmentCount * 4];
|
|
|
|
int[] triangles = new int[segmentCount * 6];
|
|
segmentCount = 0;
|
|
|
|
for (int i = 0; i < numMarks && i < maxMarks; i++) {
|
|
|
|
if (skidmarks[i].lastIndex != -1 && skidmarks[i].lastIndex > numMarks - maxMarks) {
|
|
|
|
MarkSection curr = skidmarks[i];
|
|
MarkSection last = skidmarks[curr.lastIndex % maxMarks];
|
|
|
|
if (last.pos != Vector3.zero && last.normal != Vector3.zero && Vector3.Distance(curr.pos, last.pos) < 1f) {
|
|
|
|
vertices[segmentCount * 4 + 0] = last.posl;
|
|
vertices[segmentCount * 4 + 1] = last.posr;
|
|
vertices[segmentCount * 4 + 2] = curr.posl;
|
|
vertices[segmentCount * 4 + 3] = curr.posr;
|
|
|
|
normals[segmentCount * 4 + 0] = last.normal;
|
|
normals[segmentCount * 4 + 1] = last.normal;
|
|
normals[segmentCount * 4 + 2] = curr.normal;
|
|
normals[segmentCount * 4 + 3] = curr.normal;
|
|
|
|
tangents[segmentCount * 4 + 0] = last.tangent;
|
|
tangents[segmentCount * 4 + 1] = last.tangent;
|
|
tangents[segmentCount * 4 + 2] = curr.tangent;
|
|
tangents[segmentCount * 4 + 3] = curr.tangent;
|
|
|
|
colors[segmentCount * 4 + 0] = new Color(0, 0, 0, last.intensity);
|
|
colors[segmentCount * 4 + 1] = new Color(0, 0, 0, last.intensity);
|
|
colors[segmentCount * 4 + 2] = new Color(0, 0, 0, curr.intensity);
|
|
colors[segmentCount * 4 + 3] = new Color(0, 0, 0, curr.intensity);
|
|
|
|
uvs[segmentCount * 4 + 0] = new Vector2(0, 0);
|
|
uvs[segmentCount * 4 + 1] = new Vector2(1, 0);
|
|
uvs[segmentCount * 4 + 2] = new Vector2(0, 1);
|
|
uvs[segmentCount * 4 + 3] = new Vector2(1, 1);
|
|
|
|
triangles[segmentCount * 6 + 0] = segmentCount * 4 + 0;
|
|
triangles[segmentCount * 6 + 2] = segmentCount * 4 + 1;
|
|
triangles[segmentCount * 6 + 1] = segmentCount * 4 + 2;
|
|
|
|
triangles[segmentCount * 6 + 3] = segmentCount * 4 + 2;
|
|
triangles[segmentCount * 6 + 5] = segmentCount * 4 + 1;
|
|
triangles[segmentCount * 6 + 4] = segmentCount * 4 + 3;
|
|
|
|
}
|
|
|
|
segmentCount++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
mesh.vertices = vertices;
|
|
mesh.normals = normals;
|
|
mesh.tangents = tangents;
|
|
mesh.triangles = triangles;
|
|
mesh.colors = colors;
|
|
mesh.uv = uvs;
|
|
|
|
}
|
|
|
|
/// <summary>
|
|
/// Clean all skidmarks.
|
|
/// </summary>
|
|
public void Clean() {
|
|
|
|
numMarks = 0;
|
|
updated = true;
|
|
|
|
}
|
|
|
|
} |