using System.Collections.Generic; using System.IO; using UnityEngine; namespace RoadArchitect { public class RoadConstructorBufferMaker { #region "Vars" public Road road; public List RoadVectors; public List ShoulderR_Vectors; public List ShoulderL_Vectors; public int[] tris; public int[] tris_ShoulderR; public int[] tris_ShoulderL; public Vector3[] normals; public Vector3[] normals_ShoulderR; public Vector3[] normals_ShoulderL; public List normals_ShoulderR_averageStartIndexes; public List normals_ShoulderL_averageStartIndexes; /// Road UVs public Vector2[] uv; /// Pavement UVs public Vector2[] uv2; /// Shoulder right UVs public Vector2[] uv_SR; /// Shoulder left UVs public Vector2[] uv_SL; public Vector4[] tangents; public Vector4[] tangents2; public Vector4[] tangents_SR; public Vector4[] tangents_SL; public List> cut_RoadVectors; public List cut_RoadVectorsHome; public List> cut_ShoulderR_Vectors; public List> cut_ShoulderL_Vectors; public List cut_ShoulderR_VectorsHome; public List cut_ShoulderL_VectorsHome; public List cut_tris; public List cut_tris_ShoulderR; public List cut_tris_ShoulderL; public List cut_normals; public List cut_normals_ShoulderR; public List cut_normals_ShoulderL; public List cut_uv; public List cut_uv_SR; public List cut_uv_SL; public List cut_tangents; public List cut_tangents_SR; public List cut_tangents_SL; public List cut_uv_world; public List cut_uv_SR_world; public List cut_uv_SL_world; public List cut_tangents_world; public List cut_tangents_SR_world; public List cut_tangents_SL_world; //Road connections: public List RoadConnections_verts; public List RoadConnections_tris; public List RoadConnections_normals; public List RoadConnections_uv; public List RoadConnections_tangents; //Back lanes: public List iBLane0s; public List iBLane1s; public List iBLane1s_IsMiddleLane; public List iBLane2s; public List iBLane3s; //Front lanes: public List iFLane0s; public List iFLane1s; public List iFLane1s_IsMiddleLane; public List iFLane2s; public List iFLane3s; //Main plates: public List iBMainPlates; public List iFMainPlates; //Marker plates: public List iBMarkerPlates; public List iFMarkerPlates; //Back lanes: public List iBLane0s_tris; public List iBLane1s_tris; public List iBLane2s_tris; public List iBLane3s_tris; //Front lanes: public List iFLane0s_tris; public List iFLane1s_tris; public List iFLane2s_tris; public List iFLane3s_tris; //Main plates: public List iBMainPlates_tris; public List iFMainPlates_tris; //Marker plates: public List iBMarkerPlates_tris; public List iFMarkerPlates_tris; //Back lanes: public List iBLane0s_normals; public List iBLane1s_normals; public List iBLane2s_normals; public List iBLane3s_normals; //Front lanes: public List iFLane0s_normals; public List iFLane1s_normals; public List iFLane2s_normals; public List iFLane3s_normals; //Main plates: public List iBMainPlates_normals; public List iFMainPlates_normals; //Marker plates: public List iBMarkerPlates_normals; public List iFMarkerPlates_normals; //Back lanes: public List iBLane0s_tID; public List iBLane1s_tID; public List iBLane2s_tID; public List iBLane3s_tID; //Front lanes: public List iFLane0s_tID; public List iFLane1s_tID; public List iFLane2s_tID; public List iFLane3s_tID; //Main plates: public List iBMainPlates_tID; public List iFMainPlates_tID; //Marker plates: public List iBMarkerPlates_tID; public List iFMarkerPlates_tID; //Back lanes: public List iBLane0s_nID; public List iBLane1s_nID; public List iBLane2s_nID; public List iBLane3s_nID; //Front lanes: public List iFLane0s_nID; public List iFLane1s_nID; public List iFLane2s_nID; public List iFLane3s_nID; //Main plates: public List iBMainPlates_nID; public List iFMainPlates_nID; //Marker plates: public List iBMarkerPlates_nID; public List iFMarkerPlates_nID; //Back lanes: public List iBLane0s_uv; public List iBLane1s_uv; public List iBLane2s_uv; public List iBLane3s_uv; //Front lanes: public List iFLane0s_uv; public List iFLane1s_uv; public List iFLane2s_uv; public List iFLane3s_uv; //Main plates: public List iBMainPlates_uv; public List iFMainPlates_uv; public List iBMainPlates_uv2; public List iFMainPlates_uv2; //Marker plates: public List iBMarkerPlates_uv; public List iFMarkerPlates_uv; //Back lanes: public List iBLane0s_tangents; public List iBLane1s_tangents; public List iBLane2s_tangents; public List iBLane3s_tangents; //Front lanes: public List iFLane0s_tangents; public List iFLane1s_tangents; public List iFLane2s_tangents; public List iFLane3s_tangents; //Main plates: public List iBMainPlates_tangents; public List iFMainPlates_tangents; public List iBMainPlates_tangents2; public List iFMainPlates_tangents2; //Marker plates: public List iBMarkerPlates_tangents; public List iFMarkerPlates_tangents; public Terrain tTerrain; public List tIntersectionBounds; public HashSet ImmuneVects; public Mesh tMesh; public Mesh tMesh_SR; public Mesh tMesh_SL; public bool tMeshSkip = false; public bool tMesh_SRSkip = false; public bool tMesh_SLSkip = false; public List tMesh_RoadCuts; public List tMesh_SRCuts; public List tMesh_SLCuts; public List tMesh_RoadCuts_world; public List tMesh_SRCuts_world; public List tMesh_SLCuts_world; public List tMesh_RoadConnections; public List tMesh_iBLanes0; public List tMesh_iBLanes1; public List tMesh_iBLanes2; public List tMesh_iBLanes3; public List tMesh_iFLanes0; public List tMesh_iFLanes1; public List tMesh_iFLanes2; public List tMesh_iFLanes3; public List tMesh_iBMainPlates; public List tMesh_iFMainPlates; public List tMesh_iBMarkerPlates; public List tMesh_iFMarkerPlates; public RoadUpdateTypeEnum tUpdateType; public bool isRoadOn = true; public bool isTerrainOn = true; public bool isBridgesOn = true; public bool isInterseOn = true; public List RoadCuts; public List RoadCutNodes; public List ShoulderCutsR; public List ShoulderCutsRNodes; public List ShoulderCutsL; public List ShoulderCutsLNodes; #endregion public enum SaveMeshTypeEnum { Road, Shoulder, Intersection, Railing, Center, Bridge, RoadCut, SCut, BSCut, RoadConn }; public RoadConstructorBufferMaker(Road _road, RoadUpdateTypeEnum _updateType) { tUpdateType = _updateType; isRoadOn = (tUpdateType == RoadUpdateTypeEnum.Full || tUpdateType == RoadUpdateTypeEnum.Intersection || tUpdateType == RoadUpdateTypeEnum.Bridges); isTerrainOn = (tUpdateType == RoadUpdateTypeEnum.Full || tUpdateType == RoadUpdateTypeEnum.Intersection || tUpdateType == RoadUpdateTypeEnum.Bridges); isBridgesOn = (tUpdateType == RoadUpdateTypeEnum.Full || tUpdateType == RoadUpdateTypeEnum.Bridges); isInterseOn = (tUpdateType == RoadUpdateTypeEnum.Full || tUpdateType == RoadUpdateTypeEnum.Intersection); road = _road; Nullify(); RoadVectors = new List(); ShoulderR_Vectors = new List(); ShoulderL_Vectors = new List(); normals_ShoulderR_averageStartIndexes = new List(); normals_ShoulderL_averageStartIndexes = new List(); cut_RoadVectors = new List>(); cut_RoadVectorsHome = new List(); cut_ShoulderR_Vectors = new List>(); cut_ShoulderL_Vectors = new List>(); cut_ShoulderR_VectorsHome = new List(); cut_ShoulderL_VectorsHome = new List(); cut_tris = new List(); cut_tris_ShoulderR = new List(); cut_tris_ShoulderL = new List(); cut_normals = new List(); cut_normals_ShoulderR = new List(); cut_normals_ShoulderL = new List(); cut_uv = new List(); cut_uv_SR = new List(); cut_uv_SL = new List(); cut_tangents = new List(); cut_tangents_SR = new List(); cut_tangents_SL = new List(); cut_uv_world = new List(); cut_uv_SR_world = new List(); cut_uv_SL_world = new List(); cut_tangents_world = new List(); cut_tangents_SR_world = new List(); cut_tangents_SL_world = new List(); RoadCutNodes = new List(); ShoulderCutsRNodes = new List(); ShoulderCutsLNodes = new List(); RoadConnections_verts = new List(); RoadConnections_tris = new List(); RoadConnections_normals = new List(); RoadConnections_uv = new List(); RoadConnections_tangents = new List(); RoadCuts = new List(); ShoulderCutsR = new List(); ShoulderCutsL = new List(); //if(bInterseOn){ //Back lanes: iBLane0s = new List(); iBLane1s = new List(); iBLane2s = new List(); iBLane3s = new List(); //Front lanes: iFLane0s = new List(); iFLane1s = new List(); iFLane2s = new List(); iFLane3s = new List(); //Main plates: iBMainPlates = new List(); iFMainPlates = new List(); //Marker plates: iBMarkerPlates = new List(); iFMarkerPlates = new List(); //Back lanes: iBLane0s_tris = new List(); iBLane1s_tris = new List(); iBLane2s_tris = new List(); iBLane3s_tris = new List(); //Front lanes: iFLane0s_tris = new List(); iFLane1s_tris = new List(); iFLane2s_tris = new List(); iFLane3s_tris = new List(); //Main plates: iBMainPlates_tris = new List(); iFMainPlates_tris = new List(); //Marker plates: iBMarkerPlates_tris = new List(); iFMarkerPlates_tris = new List(); //Back lanes: iBLane0s_normals = new List(); iBLane1s_normals = new List(); iBLane2s_normals = new List(); iBLane3s_normals = new List(); //Front lanes: iFLane0s_normals = new List(); iFLane1s_normals = new List(); iFLane2s_normals = new List(); iFLane3s_normals = new List(); //Main plates: iBMainPlates_normals = new List(); iFMainPlates_normals = new List(); //Marker plates: iBMarkerPlates_normals = new List(); iFMarkerPlates_normals = new List(); //Back lanes: iBLane0s_uv = new List(); iBLane1s_uv = new List(); iBLane2s_uv = new List(); iBLane3s_uv = new List(); //Front lanes: iFLane0s_uv = new List(); iFLane1s_uv = new List(); iFLane2s_uv = new List(); iFLane3s_uv = new List(); //Main plates: iBMainPlates_uv = new List(); iFMainPlates_uv = new List(); iBMainPlates_uv2 = new List(); iFMainPlates_uv2 = new List(); //Marker plates: iBMarkerPlates_uv = new List(); iFMarkerPlates_uv = new List(); //Back lanes: iBLane0s_tangents = new List(); iBLane1s_tangents = new List(); iBLane2s_tangents = new List(); iBLane3s_tangents = new List(); //Front lanes: iFLane0s_tangents = new List(); iFLane1s_tangents = new List(); iFLane2s_tangents = new List(); iFLane3s_tangents = new List(); //Main plates: iBMainPlates_tangents = new List(); iFMainPlates_tangents = new List(); iBMainPlates_tangents2 = new List(); iFMainPlates_tangents2 = new List(); //Marker plates: iBMarkerPlates_tangents = new List(); iFMarkerPlates_tangents = new List(); iFLane1s_IsMiddleLane = new List(); iBLane1s_IsMiddleLane = new List(); //Back lanes: iBLane0s_tID = new List(); iBLane1s_tID = new List(); iBLane2s_tID = new List(); iBLane3s_tID = new List(); //Front lanes: iFLane0s_tID = new List(); iFLane1s_tID = new List(); iFLane2s_tID = new List(); iFLane3s_tID = new List(); //Main plates: iBMainPlates_tID = new List(); iFMainPlates_tID = new List(); //Marker plates: iBMarkerPlates_tID = new List(); iFMarkerPlates_tID = new List(); iBLane0s_nID = new List(); iBLane1s_nID = new List(); iBLane2s_nID = new List(); iBLane3s_nID = new List(); //Front lanes: iFLane0s_nID = new List(); iFLane1s_nID = new List(); iFLane2s_nID = new List(); iFLane3s_nID = new List(); //Main plates: iBMainPlates_nID = new List(); iFMainPlates_nID = new List(); //Marker plates: iBMarkerPlates_nID = new List(); iFMarkerPlates_nID = new List(); //} tTerrain = null; tMesh = new Mesh(); tMesh_SR = new Mesh(); tMesh_SL = new Mesh(); tMesh_RoadCuts = new List(); tMesh_SRCuts = new List(); tMesh_SLCuts = new List(); tMesh_RoadCuts_world = new List(); tMesh_SRCuts_world = new List(); tMesh_SLCuts_world = new List(); tMesh_RoadConnections = new List(); //if(bInterseOn){ tMesh_iBLanes0 = new List(); tMesh_iBLanes1 = new List(); tMesh_iBLanes2 = new List(); tMesh_iBLanes3 = new List(); tMesh_iFLanes0 = new List(); tMesh_iFLanes1 = new List(); tMesh_iFLanes2 = new List(); tMesh_iFLanes3 = new List(); tMesh_iBMainPlates = new List(); tMesh_iFMainPlates = new List(); tMesh_iBMarkerPlates = new List(); tMesh_iFMarkerPlates = new List(); tIntersectionBounds = new List(); ImmuneVects = new HashSet(); //} InitGameObjects(); } #region "Init and nullify" private void InitGameObjects() { //Destry past objects: if (road.MainMeshes != null) { MeshFilter[] MFArray = road.MainMeshes.GetComponentsInChildren(); MeshCollider[] MCArray = road.MainMeshes.GetComponentsInChildren(); int MFArrayCount = MFArray.Length; int MCArrayCount = MCArray.Length; for (int index = (MFArrayCount - 1); index > -1; index--) { MFArray[index].sharedMesh = null; } for (int index = (MCArrayCount - 1); index > -1; index--) { MCArray[index].sharedMesh = null; } Object.DestroyImmediate(road.MainMeshes); } //Main mesh object: road.MainMeshes = new GameObject("MainMeshes"); road.MainMeshes.transform.parent = road.transform; //Road and shoulders: road.MeshRoad = new GameObject("RoadMesh"); road.MeshShoR = new GameObject("ShoulderR"); road.MeshShoL = new GameObject("ShoulderL"); road.MeshRoad.transform.parent = road.MainMeshes.transform; road.MeshShoR.transform.parent = road.MainMeshes.transform; road.MeshShoL.transform.parent = road.MainMeshes.transform; //Intersections: road.MeshiLanes = new GameObject("MeshiLanes"); road.MeshiLanes0 = new GameObject("MeshiLanes0"); road.MeshiLanes1 = new GameObject("MeshiLanes1"); road.MeshiLanes2 = new GameObject("MeshiLanes2"); road.MeshiLanes3 = new GameObject("MeshiLanes3"); road.MeshiMainPlates = new GameObject("MeshiMainPlates"); road.MeshiMarkerPlates = new GameObject("MeshiMarkerPlates"); road.MeshiLanes.transform.parent = road.MainMeshes.transform; road.MeshiLanes0.transform.parent = road.MainMeshes.transform; road.MeshiLanes1.transform.parent = road.MainMeshes.transform; road.MeshiLanes2.transform.parent = road.MainMeshes.transform; road.MeshiLanes3.transform.parent = road.MainMeshes.transform; road.MeshiMainPlates.transform.parent = road.MainMeshes.transform; road.MeshiMarkerPlates.transform.parent = road.MainMeshes.transform; } public void Nullify() { RoadVectors = null; ShoulderR_Vectors = null; ShoulderL_Vectors = null; tris = null; normals = null; uv = null; uv_SR = null; uv_SL = null; tangents = null; tangents_SR = null; tangents_SL = null; tTerrain = null; tIntersectionBounds = null; ImmuneVects = null; iBLane0s = null; iBLane1s = null; iBLane2s = null; iBLane3s = null; iFLane0s = null; iFLane1s = null; iFLane2s = null; iFLane3s = null; iBMainPlates = null; iFMainPlates = null; iBMarkerPlates = null; iFMarkerPlates = null; tMesh = null; tMesh_SR = null; tMesh_SL = null; RootUtils.NullifyList(ref tMesh_iBLanes0); RootUtils.NullifyList(ref tMesh_iBLanes1); RootUtils.NullifyList(ref tMesh_iBLanes2); RootUtils.NullifyList(ref tMesh_iBLanes3); RootUtils.NullifyList(ref tMesh_iFLanes0); RootUtils.NullifyList(ref tMesh_iFLanes1); RootUtils.NullifyList(ref tMesh_iFLanes2); RootUtils.NullifyList(ref tMesh_iFLanes3); RootUtils.NullifyList(ref tMesh_iBMainPlates); RootUtils.NullifyList(ref tMesh_iFMainPlates); RootUtils.NullifyList(ref tMesh_iBMarkerPlates); RootUtils.NullifyList(ref tMesh_iFMarkerPlates); tMesh_RoadConnections = null; iFLane1s_IsMiddleLane = null; iBLane1s_IsMiddleLane = null; RoadConnections_verts = null; RoadConnections_tris = null; RoadConnections_normals = null; RoadConnections_uv = null; RoadConnections_tangents = null; RootUtils.NullifyList(ref cut_uv_world); RootUtils.NullifyList(ref cut_uv_SR_world); RootUtils.NullifyList(ref cut_uv_SL_world); RootUtils.NullifyList(ref cut_tangents_world); RootUtils.NullifyList(ref cut_tangents_SR_world); RootUtils.NullifyList(ref cut_tangents_SL_world); tMesh = null; tMesh_SR = null; tMesh_SL = null; tMesh_SR = null; tMesh_SL = null; tMesh_RoadCuts = null; tMesh_SRCuts = null; tMesh_SLCuts = null; tMesh_RoadCuts_world = null; tMesh_SRCuts_world = null; tMesh_SLCuts_world = null; } #endregion #region "Mesh Setup1" /// /// Creates meshes and assigns vertices, triangles and normals. If multithreading enabled, this occurs inbetween threaded jobs since unity library can't be used in threads. /// public void MeshSetup1() { Mesh MeshBuffer = null; if (isInterseOn) { MeshSetup1IntersectionObjectsSetup(); } if (isRoadOn) { //Main road: if (RoadVectors.Count < 64000) { if (tMesh == null) { tMesh = new Mesh(); } tMesh = MeshSetup1Helper(ref tMesh, RoadVectors.ToArray(), ref tris, ref normals); tMeshSkip = false; } else { tMeshSkip = true; } //Right shoulder: if (ShoulderR_Vectors.Count < 64000) { if (tMesh_SR == null) { tMesh_SR = new Mesh(); } tMesh_SR = MeshSetup1Helper(ref tMesh_SR, ShoulderR_Vectors.ToArray(), ref tris_ShoulderR, ref normals_ShoulderR); tMesh_SRSkip = false; } else { tMesh_SRSkip = true; } //Left shoulder: if (ShoulderL_Vectors.Count < 64000) { if (tMesh_SL == null) { tMesh_SL = new Mesh(); } tMesh_SL = MeshSetup1Helper(ref tMesh_SL, ShoulderL_Vectors.ToArray(), ref tris_ShoulderL, ref normals_ShoulderL); tMesh_SLSkip = false; } else { tMesh_SLSkip = true; } if (RoadConnections_verts.Count > 0) { Mesh qMesh = null; for (int index = 0; index < RoadConnections_verts.Count; index++) { qMesh = new Mesh(); qMesh.vertices = RoadConnections_verts[index]; qMesh.triangles = RoadConnections_tris[index]; qMesh.normals = RoadConnections_normals[index]; qMesh.uv = RoadConnections_uv[index]; qMesh.RecalculateNormals(); RoadConnections_normals[index] = qMesh.normals; tMesh_RoadConnections.Add(qMesh); } } if ((road.isRoadCutsEnabled || road.isDynamicCutsEnabled) && RoadCuts.Count > 0) { int[] tTris = null; Vector3[] tNormals = null; int cCount = cut_RoadVectors.Count; for (int index = 0; index < cCount; index++) { tTris = cut_tris[index]; tNormals = cut_normals[index]; MeshBuffer = new Mesh(); tMesh_RoadCuts.Add(MeshSetup1Helper(ref MeshBuffer, cut_RoadVectors[index].ToArray(), ref tTris, ref tNormals)); MeshBuffer = new Mesh(); tMesh_RoadCuts_world.Add(MeshSetup1Helper(ref MeshBuffer, cut_RoadVectors[index].ToArray(), ref tTris, ref tNormals)); cut_normals[index] = tNormals; tMeshSkip = true; } } if (road.isShoulderCutsEnabled || road.isDynamicCutsEnabled) { int[] tTris = null; Vector3[] tNormals = null; int rCount = cut_ShoulderR_Vectors.Count; for (int index = 0; index < rCount; index++) { tTris = cut_tris_ShoulderR[index]; tNormals = cut_normals_ShoulderR[index]; MeshBuffer = new Mesh(); tMesh_SRCuts.Add(MeshSetup1Helper(ref MeshBuffer, cut_ShoulderR_Vectors[index].ToArray(), ref tTris, ref tNormals)); MeshBuffer = new Mesh(); tMesh_SRCuts_world.Add(MeshSetup1Helper(ref MeshBuffer, cut_ShoulderR_Vectors[index].ToArray(), ref tTris, ref tNormals)); cut_normals_ShoulderR[index] = tNormals; tMesh_SRSkip = true; } if (rCount <= 0) { tMesh_SRSkip = false; } int lCount = cut_ShoulderL_Vectors.Count; for (int index = 0; index < lCount; index++) { tTris = cut_tris_ShoulderL[index]; tNormals = cut_normals_ShoulderL[index]; MeshBuffer = new Mesh(); tMesh_SLCuts.Add(MeshSetup1Helper(ref MeshBuffer, cut_ShoulderL_Vectors[index].ToArray(), ref tTris, ref tNormals)); MeshBuffer = new Mesh(); tMesh_SLCuts_world.Add(MeshSetup1Helper(ref MeshBuffer, cut_ShoulderL_Vectors[index].ToArray(), ref tTris, ref tNormals)); cut_normals_ShoulderL[index] = tNormals; tMesh_SLSkip = true; } if (lCount <= 0) { tMesh_SLSkip = false; } } } if (isInterseOn) { MeshSetup1IntersectionParts(); } MeshBuffer = null; } #region "Intersection for MeshSetup1" /// Cleanup and create intersection objects private void MeshSetup1IntersectionObjectsSetup() { int nodeCount = road.spline.GetNodeCount(); List roadIntersections = new List(); for (int index = 0; index < nodeCount; index++) { if (road.spline.nodes[index].isIntersection) { if (!roadIntersections.Contains(road.spline.nodes[index].intersection)) { roadIntersections.Add(road.spline.nodes[index].intersection); } } } //Cleanups: foreach (RoadIntersection intersection in roadIntersections) { IntersectionObjects.CleanupIntersectionObjects(intersection.transform.gameObject); if (intersection.intersectionStopType == RoadIntersection.iStopTypeEnum.StopSign_AllWay) { IntersectionObjects.CreateStopSignsAllWay(intersection.transform.gameObject, true); } else if (intersection.intersectionStopType == RoadIntersection.iStopTypeEnum.TrafficLight1) { IntersectionObjects.CreateTrafficLightBases(intersection.transform.gameObject, true); } else if (intersection.intersectionStopType == RoadIntersection.iStopTypeEnum.TrafficLight2) { } else if (intersection.intersectionStopType == RoadIntersection.iStopTypeEnum.None) { //Do nothing. } } } /// Creates intersection meshes if road contains intersections private void MeshSetup1IntersectionParts() { int mCount = road.spline.GetNodeCount(); bool bHasInter = false; for (int index = 0; index < mCount; index++) { if (road.spline.nodes[index].isIntersection) { bHasInter = true; break; } } if (!bHasInter) { return; } int vCount = -1; Mesh MeshBuffer = null; Vector3[] tNormals = null; int[] tTris = null; //Back lanes: vCount = iBLane0s.Count; for (int i = 0; i < vCount; i++) { tNormals = iBLane0s_normals[i]; tTris = iBLane0s_tris[i]; MeshBuffer = new Mesh(); MeshBuffer = MeshSetup1Helper(ref MeshBuffer, iBLane0s[i], ref tTris, ref tNormals); tMesh_iBLanes0.Add(MeshBuffer); } vCount = iBLane1s.Count; for (int index = 0; index < vCount; index++) { tNormals = iBLane1s_normals[index]; tTris = iBLane1s_tris[index]; MeshBuffer = new Mesh(); MeshBuffer = MeshSetup1Helper(ref MeshBuffer, iBLane1s[index], ref tTris, ref tNormals); tMesh_iBLanes1.Add(MeshBuffer); } vCount = iBLane2s.Count; for (int index = 0; index < vCount; index++) { tNormals = iBLane2s_normals[index]; tTris = iBLane2s_tris[index]; MeshBuffer = new Mesh(); MeshBuffer = MeshSetup1Helper(ref MeshBuffer, iBLane2s[index], ref tTris, ref tNormals); tMesh_iBLanes2.Add(MeshBuffer); } vCount = iBLane3s.Count; for (int index = 0; index < vCount; index++) { tNormals = iBLane3s_normals[index]; tTris = iBLane3s_tris[index]; MeshBuffer = new Mesh(); MeshBuffer = MeshSetup1Helper(ref MeshBuffer, iBLane3s[index], ref tTris, ref tNormals); tMesh_iBLanes3.Add(MeshBuffer); } //Front lanes: vCount = iFLane0s.Count; for (int i = 0; i < vCount; i++) { tNormals = iFLane0s_normals[i]; tTris = iFLane0s_tris[i]; MeshBuffer = new Mesh(); MeshBuffer = MeshSetup1Helper(ref MeshBuffer, iFLane0s[i], ref tTris, ref tNormals); tMesh_iFLanes0.Add(MeshBuffer); } vCount = iFLane1s.Count; for (int index = 0; index < vCount; index++) { tNormals = iFLane1s_normals[index]; tTris = iFLane1s_tris[index]; MeshBuffer = new Mesh(); MeshBuffer = MeshSetup1Helper(ref MeshBuffer, iFLane1s[index], ref tTris, ref tNormals); tMesh_iFLanes1.Add(MeshBuffer); } vCount = iFLane2s.Count; for (int index = 0; index < vCount; index++) { tNormals = iFLane2s_normals[index]; tTris = iFLane2s_tris[index]; MeshBuffer = new Mesh(); MeshBuffer = MeshSetup1Helper(ref MeshBuffer, iFLane2s[index], ref tTris, ref tNormals); tMesh_iFLanes2.Add(MeshBuffer); } vCount = iFLane3s.Count; for (int index = 0; index < vCount; index++) { tNormals = iFLane3s_normals[index]; tTris = iFLane3s_tris[index]; MeshBuffer = new Mesh(); MeshBuffer = MeshSetup1Helper(ref MeshBuffer, iFLane3s[index], ref tTris, ref tNormals); tMesh_iFLanes3.Add(MeshBuffer); } //Main plates: vCount = iBMainPlates.Count; for (int index = 0; index < vCount; index++) { tNormals = iBMainPlates_normals[index]; tTris = iBMainPlates_tris[index]; MeshBuffer = new Mesh(); MeshBuffer = MeshSetup1Helper(ref MeshBuffer, iBMainPlates[index], ref tTris, ref tNormals); tMesh_iBMainPlates.Add(MeshBuffer); } vCount = iFMainPlates.Count; for (int index = 0; index < vCount; index++) { tNormals = iFMainPlates_normals[index]; tTris = iFMainPlates_tris[index]; MeshBuffer = new Mesh(); MeshBuffer = MeshSetup1Helper(ref MeshBuffer, iFMainPlates[index], ref tTris, ref tNormals); tMesh_iFMainPlates.Add(MeshBuffer); } MeshBuffer = null; } #endregion /// Assigns mesh values to _mesh and returns _mesh private Mesh MeshSetup1Helper(ref Mesh _mesh, Vector3[] _verts, ref int[] _tris, ref Vector3[] _normals) { _mesh.vertices = _verts; _mesh.triangles = _tris; _mesh.normals = _normals; _mesh.RecalculateNormals(); _normals = _mesh.normals; //_mesh.hideFlags = HideFlags.DontSave; return _mesh; } #endregion #region "Mesh Setup2" /// /// Assigns UV and tangents to meshes. If multithreading enabled, this occurs after the last threaded job since unity library can't be used in threads. /// public void MeshSetup2() { Mesh MeshMainBuffer = null; Mesh MeshMarkerBuffer = null; if (isRoadOn) { // Materials batched and extracted from inner for loops of mesh creation Material[] markerMaterialsField = road.GetRoadMarkerMaterials(); Material[] roadMaterialsField = road.GetRoadWorldMaterials(); // shoulder fields only contain data when isShouldersEnabled Material[] shoulderMaterialsField = road.GetShoulderWorldMaterials(); Material[] shoulderMarkerMaterialsField = road.GetShoulderMarkerMaterials(); //If road cuts is off, full size UVs: if ((!road.isRoadCutsEnabled && !road.isDynamicCutsEnabled) || (RoadCuts == null || RoadCuts.Count <= 0)) { if (tMesh != null) { tMesh = MeshSetup2Helper(ref tMesh, uv, tangents, ref road.MeshRoad, shoulderMaterialsField, markerMaterialsField, roadMaterialsField, true); SaveMesh(SaveMeshTypeEnum.Road, tMesh, road, road.MeshRoad.transform.name); Vector3[] ooVerts = new Vector3[tMesh.vertexCount]; int[] ooTris = new int[tMesh.triangles.Length]; Vector3[] ooNormals = new Vector3[tMesh.normals.Length]; Vector2[] ooUV = new Vector2[uv2.Length]; Vector4[] ooTangents = new Vector4[tangents2.Length]; // Copy mesh values System.Array.Copy(tMesh.vertices, ooVerts, ooVerts.Length); System.Array.Copy(tMesh.triangles, ooTris, ooTris.Length); System.Array.Copy(tMesh.normals, ooNormals, ooNormals.Length); System.Array.Copy(uv2, ooUV, ooUV.Length); System.Array.Copy(tangents2, ooTangents, ooTangents.Length); Mesh pMesh = new Mesh(); pMesh.vertices = ooVerts; pMesh.triangles = ooTris; pMesh.normals = ooNormals; pMesh.uv = ooUV; pMesh.tangents = ooTangents; GameObject gObj = new GameObject("Pavement"); pMesh = MeshSetup2Helper(ref pMesh, uv2, tangents2, ref gObj, shoulderMaterialsField, markerMaterialsField, roadMaterialsField, false); //Road markers stored on parent "MeshRoad" game object, with a "Pavement" child game object storing the asphalt. gObj.transform.parent = road.MeshRoad.transform; SaveMesh(SaveMeshTypeEnum.Road, pMesh, road, gObj.transform.name); } } else { //If road cuts, change it to one material (pavement) with world mapping int cCount = cut_RoadVectors.Count; //Vector2[] tUV; bool bHasMats; GameObject CreatedMainObj; GameObject CreatedMarkerObj; for (int i = 0; i < cCount; i++) { CreatedMainObj = null; MeshMainBuffer = tMesh_RoadCuts_world[i]; if (MeshMainBuffer != null) { MeshSetup2HelperRoadCuts(i, ref MeshMainBuffer, cut_uv_world[i], cut_tangents_world[i], ref road.MeshRoad, false, out CreatedMainObj, markerMaterialsField, roadMaterialsField); SaveMesh(SaveMeshTypeEnum.RoadCut, MeshMainBuffer, road, "RoadCut" + i.ToString()); } CreatedMarkerObj = null; MeshMarkerBuffer = tMesh_RoadCuts[i]; if (MeshMarkerBuffer != null) { bHasMats = MeshSetup2HelperRoadCuts(i, ref MeshMarkerBuffer, cut_uv[i], cut_tangents[i], ref CreatedMainObj, true, out CreatedMarkerObj, markerMaterialsField, roadMaterialsField); if (bHasMats) { SaveMesh(SaveMeshTypeEnum.RoadCut, MeshMarkerBuffer, road, "RoadCutMarker" + i.ToString()); } else { //Destroy if no marker materials: Object.DestroyImmediate(CreatedMarkerObj); Object.DestroyImmediate(MeshMarkerBuffer); } } } //Remove main mesh stuff if necessary: if (road.MeshRoad != null) { MeshCollider tMC = road.MeshRoad.GetComponent(); MeshRenderer tMR = road.MeshRoad.GetComponent(); Object.DestroyImmediate(tMC); Object.DestroyImmediate(tMR); } Object.DestroyImmediate(tMesh); } //Shoulders: if (road.isShouldersEnabled) { if ((!road.isShoulderCutsEnabled && !road.isDynamicCutsEnabled) || (ShoulderCutsL == null || cut_ShoulderL_Vectors.Count <= 0)) { //Right road shoulder: if (tMesh_SR != null) { tMesh_SR = MeshSetup2Helper(ref tMesh_SR, uv_SR, tangents_SR, ref road.MeshShoR, shoulderMaterialsField, markerMaterialsField, roadMaterialsField, false, true); SaveMesh(SaveMeshTypeEnum.Shoulder, tMesh_SR, road, road.MeshShoR.transform.name); } //Left road shoulder: if (tMesh_SL != null) { tMesh_SL = MeshSetup2Helper(ref tMesh_SL, uv_SL, tangents_SL, ref road.MeshShoL, shoulderMaterialsField, markerMaterialsField, roadMaterialsField, false, true); SaveMesh(SaveMeshTypeEnum.Shoulder, tMesh_SL, road, road.MeshShoL.transform.name); } } else { bool bHasMats; GameObject CreatedMainObj; GameObject CreatedMarkerObj; int rCount = cut_ShoulderR_Vectors.Count; for (int index = 0; index < rCount; index++) { CreatedMainObj = null; MeshMainBuffer = tMesh_SRCuts_world[index]; if (MeshMainBuffer != null) { MeshSetup2HelperCutsShoulder(index, ref MeshMainBuffer, cut_uv_SR_world[index], cut_tangents_SR_world[index], ref road.MeshShoR, false, false, out CreatedMainObj, shoulderMarkerMaterialsField, shoulderMaterialsField); SaveMesh(SaveMeshTypeEnum.SCut, MeshMainBuffer, road, "SCutR" + index.ToString()); } CreatedMarkerObj = null; MeshMarkerBuffer = tMesh_SRCuts[index]; if (MeshMarkerBuffer != null) { bHasMats = MeshSetup2HelperCutsShoulder(index, ref MeshMarkerBuffer, cut_uv_SR[index], cut_tangents_SR[index], ref CreatedMainObj, false, true, out CreatedMarkerObj, shoulderMarkerMaterialsField, shoulderMaterialsField); if (bHasMats) { SaveMesh(SaveMeshTypeEnum.SCut, MeshMarkerBuffer, road, "SCutRMarker" + index.ToString()); } else { //Destroy if no marker materials: Object.DestroyImmediate(CreatedMarkerObj); Object.DestroyImmediate(MeshMarkerBuffer); } } } int lCount = cut_ShoulderL_Vectors.Count; for (int index = 0; index < lCount; index++) { CreatedMainObj = null; MeshMainBuffer = tMesh_SLCuts_world[index]; if (MeshMainBuffer != null) { MeshSetup2HelperCutsShoulder(index, ref MeshMainBuffer, cut_uv_SL_world[index], cut_tangents_SL_world[index], ref road.MeshShoL, true, false, out CreatedMainObj, shoulderMarkerMaterialsField, shoulderMaterialsField); SaveMesh(SaveMeshTypeEnum.SCut, MeshMainBuffer, road, "SCutL" + index.ToString()); } CreatedMarkerObj = null; MeshMarkerBuffer = tMesh_SLCuts[index]; if (MeshMarkerBuffer != null) { bHasMats = MeshSetup2HelperCutsShoulder(index, ref MeshMarkerBuffer, cut_uv_SL[index], cut_tangents_SL[index], ref CreatedMainObj, true, true, out CreatedMarkerObj, shoulderMarkerMaterialsField, shoulderMaterialsField); if (bHasMats) { SaveMesh(SaveMeshTypeEnum.SCut, MeshMarkerBuffer, road, "SCutLMarker" + index.ToString()); } else { //Destroy if no marker materials: Object.DestroyImmediate(CreatedMarkerObj); Object.DestroyImmediate(MeshMarkerBuffer); } } } if (road.isUsingMeshColliders) { //MeshSetup2IntersectionsFixNormals(); } RemoveMainMeshes(); } } else { RemoveMainMeshes(); int xCount = tMesh_SRCuts_world.Count; for (int index = 0; index < xCount; index++) { Object.DestroyImmediate(tMesh_SRCuts_world[index]); } tMesh_SRCuts_world.Clear(); xCount = tMesh_SRCuts.Count; for (int index = 0; index < xCount; index++) { Object.DestroyImmediate(tMesh_SRCuts[index]); } tMesh_SRCuts.Clear(); xCount = tMesh_SLCuts_world.Count; for (int index = 0; index < xCount; index++) { Object.DestroyImmediate(tMesh_SLCuts_world[index]); } tMesh_SLCuts_world.Clear(); xCount = tMesh_SLCuts.Count; for (int index = 0; index < xCount; index++) { Object.DestroyImmediate(tMesh_SLCuts[index]); } tMesh_SLCuts.Clear(); Object.DestroyImmediate(road.MeshShoR); Object.DestroyImmediate(road.MeshShoL); } string basePath = RoadEditorUtility.GetBasePath(); for (int index = 0; index < RoadConnections_tangents.Count; index++) { tMesh_RoadConnections[index].tangents = RoadConnections_tangents[index]; GameObject tObj = new GameObject("RoadConnectionMarker"); MeshFilter MF = tObj.AddComponent(); MeshRenderer MR = tObj.AddComponent(); float fDist = Vector3.Distance(RoadConnections_verts[index][2], RoadConnections_verts[index][3]); fDist = Mathf.Round(fDist); if (road.laneAmount == 2) { if (fDist == Mathf.Round(road.RoadWidth() * 2f)) { RoadEditorUtility.SetRoadMaterial(basePath + "/Materials/Markers/RoadConn-4L.mat", MR); } else if (fDist == Mathf.Round(road.RoadWidth() * 3f)) { RoadEditorUtility.SetRoadMaterial(basePath + "/Materials/Markers/RoadConn-6L-2L.mat", MR); } } else if (road.laneAmount == 4) { if (fDist == Mathf.Round(road.RoadWidth() * 1.5f)) { RoadEditorUtility.SetRoadMaterial(basePath + "/Materials/Markers/RoadConn-6L-4L.mat", MR); } } MF.sharedMesh = tMesh_RoadConnections[index]; tObj.transform.parent = road.MeshRoad.transform; Mesh vMesh = new Mesh(); vMesh.vertices = RoadConnections_verts[index]; vMesh.triangles = RoadConnections_tris[index]; vMesh.normals = RoadConnections_normals[index]; Vector2[] vUV = new Vector2[4]; vUV[0] = new Vector2(RoadConnections_verts[index][0].x / 5f, RoadConnections_verts[index][0].z / 5f); vUV[1] = new Vector2(RoadConnections_verts[index][1].x / 5f, RoadConnections_verts[index][1].z / 5f); vUV[2] = new Vector2(RoadConnections_verts[index][2].x / 5f, RoadConnections_verts[index][2].z / 5f); vUV[3] = new Vector2(RoadConnections_verts[index][3].x / 5f, RoadConnections_verts[index][3].z / 5f); vMesh.uv = vUV; vMesh.RecalculateNormals(); RoadConnections_normals[index] = vMesh.normals; vMesh.tangents = RootUtils.ProcessTangents(vMesh.triangles, vMesh.normals, vMesh.uv, vMesh.vertices); tObj = new GameObject("RoadConnectionBase"); MF = tObj.AddComponent(); MR = tObj.AddComponent(); MeshCollider MC = tObj.AddComponent(); MF.sharedMesh = vMesh; MC.sharedMesh = MF.sharedMesh; RoadEditorUtility.SetRoadMaterial(basePath + "/Materials/Road1.mat", MR); tObj.transform.parent = road.MeshRoad.transform; SaveMesh(SaveMeshTypeEnum.RoadConn, vMesh, road, "RoadConn" + index.ToString()); } } if (isInterseOn) { MeshSetup2Intersections(); } Object.DestroyImmediate(road.MeshiLanes); Object.DestroyImmediate(road.MeshiLanes0); Object.DestroyImmediate(road.MeshiLanes1); Object.DestroyImmediate(road.MeshiLanes2); Object.DestroyImmediate(road.MeshiLanes3); Object.DestroyImmediate(road.MeshiMainPlates); Object.DestroyImmediate(road.MeshiMarkerPlates); //Updates the road and shoulder cut materials if necessary. //Note: Cycling through all nodes in case the road cuts and shoulder cut numbers don't match. if (road.isRoadCutsEnabled || road.isShoulderCutsEnabled || road.isDynamicCutsEnabled) { int mCount = road.spline.GetNodeCount(); for (int index = 0; index < mCount; index++) { road.spline.nodes[index].UpdateCuts(); } } } private void RemoveMainMeshes() { //Remove main mesh stuff if necessary: Object.DestroyImmediate(tMesh_SR); Object.DestroyImmediate(tMesh_SL); if (road.MeshShoR != null) { MeshCollider tMC = road.MeshShoR.GetComponent(); MeshRenderer tMR = road.MeshShoR.GetComponent(); Object.DestroyImmediate(tMC); Object.DestroyImmediate(tMR); } if (road.MeshShoL != null) { MeshCollider tMC = road.MeshShoL.GetComponent(); MeshRenderer tMR = road.MeshShoL.GetComponent(); Object.DestroyImmediate(tMC); Object.DestroyImmediate(tMR); } } #region "MeshSetup2 - Intersections" //private void MeshSetup2IntersectionsFixNormals() //{ // int mCount = tRoad.spline.GetNodeCount(); // SplineN tNode = null; // RoadIntersection roadIntersection = null; // float MaxDist = 0f; // float[] tDists = new float[2]; // Collider[] tColliders = null; // List tCuts = null; // // for(int h=0; h(); // foreach(Collider tCollider in tColliders) // { // if(tCollider.transform.name.Contains("cut")) // { // tCuts.Add(tCollider.transform.gameObject); // } // } // // // foreach(GameObject tObj in tCuts) // { // MeshFilter MF1 = tCuts[0].GetComponent(); // if(MF1 == null) // { // continue; // } // Mesh zMesh1 = MF1.sharedMesh; // Vector3[] tVerts1 = zMesh1.vertices; // Vector3[] tNormals1 = zMesh1.normals; // int MVL1 = tVerts1.Length; // for(int i=0; i Creates main roads of the intersections if road contains intersections private void MeshSetup2Intersections() { int mCount = road.spline.GetNodeCount(); bool bHasInter = false; for (int index = 0; index < mCount; index++) { if (road.spline.nodes[index].isIntersection) { bHasInter = true; break; } } if (!bHasInter) { return; } int vCount = -1; Mesh xMesh = null; Vector2[] tUV = null; Vector4[] tTangents = null; MeshFilter MF = null; Dictionary> tCombineDict_Lane0 = new Dictionary>(); Dictionary> tCombineDict_Lane1 = new Dictionary>(); Dictionary> tCombineDict_Lane2 = new Dictionary>(); Dictionary> tCombineDict_Lane3 = new Dictionary>(); Dictionary> tCombineDict_MainPlate = new Dictionary>(); Dictionary> tCombineDict_MainPlateM = new Dictionary>(); HashSet uniqueRoadIntersection = new HashSet(); Dictionary> tCombineDict_Lane1_Disabled = new Dictionary>(); Dictionary> tCombineDict_Lane2_Disabled = new Dictionary>(); Dictionary> tCombineDict_Lane2_DisabledActive = new Dictionary>(); Dictionary> tCombineDict_Lane2_DisabledActiveR = new Dictionary>(); Dictionary> tCombineDict_Lane3_Disabled = new Dictionary>(); Dictionary> tCombineDict_Lane1_DisabledActive = new Dictionary>(); string basePath = RoadEditorUtility.GetBasePath(); vCount = iBLane0s.Count; for (int index = 0; index < vCount; index++) { tUV = iBLane0s_uv[index]; tTangents = iBLane0s_tangents[index]; xMesh = tMesh_iBLanes0[index]; MF = MeshSetup2IntersectionHelper(ref xMesh, ref tUV, ref tTangents, ref road.MeshiLanes0, "Lane0B", basePath + "/Materials/Markers/InterWhiteLYellowR.mat"); if (!tCombineDict_Lane0.ContainsKey(iBLane0s_tID[index])) { tCombineDict_Lane0.Add(iBLane0s_tID[index], new List()); } tCombineDict_Lane0[iBLane0s_tID[index]].Add(MF); } vCount = iBLane1s.Count; for (int index = 0; index < vCount; index++) { bool isPrimaryNode = (iBLane1s_tID[index].node1 == iBLane1s_nID[index]); if (!isPrimaryNode && iBLane1s_tID[index].intersectionType == RoadIntersection.IntersectionTypeEnum.ThreeWay && (iBLane1s_tID[index].roadType == RoadIntersection.RoadTypeEnum.TurnLane || iBLane1s_tID[index].roadType == RoadIntersection.RoadTypeEnum.BothTurnLanes) && !iBLane1s_tID[index].isNode2BLeftTurnLane) { tUV = iBLane1s_uv[index]; tTangents = iBLane1s_tangents[index]; xMesh = tMesh_iBLanes1[index]; MF = MeshSetup2IntersectionHelper(ref xMesh, ref tUV, ref tTangents, ref road.MeshiLanes1, "LaneD1B", basePath + "/Materials/Markers/InterLaneDisabled.mat"); if (!tCombineDict_Lane1_Disabled.ContainsKey(iBLane1s_tID[index])) { tCombineDict_Lane1_Disabled.Add(iBLane1s_tID[index], new List()); } tCombineDict_Lane1_Disabled[iBLane1s_tID[index]].Add(MF); } else if (isPrimaryNode && iBLane1s_tID[index].intersectionType == RoadIntersection.IntersectionTypeEnum.ThreeWay && iBLane1s_tID[index].roadType == RoadIntersection.RoadTypeEnum.BothTurnLanes) { tUV = iBLane1s_uv[index]; tTangents = iBLane1s_tangents[index]; xMesh = tMesh_iBLanes1[index]; MF = MeshSetup2IntersectionHelper(ref xMesh, ref tUV, ref tTangents, ref road.MeshiLanes1, "LaneDA1B", basePath + "/Materials/Markers/InterLaneDisabledOuter.mat"); if (!tCombineDict_Lane1_DisabledActive.ContainsKey(iBLane1s_tID[index])) { tCombineDict_Lane1_DisabledActive.Add(iBLane1s_tID[index], new List()); } tCombineDict_Lane1_DisabledActive[iBLane1s_tID[index]].Add(MF); } else { tUV = iBLane1s_uv[index]; tTangents = iBLane1s_tangents[index]; xMesh = tMesh_iBLanes1[index]; MF = MeshSetup2IntersectionHelper(ref xMesh, ref tUV, ref tTangents, ref road.MeshiLanes1, "Lane1B", basePath + "/Materials/Markers/InterYellowLWhiteR.mat"); if (!tCombineDict_Lane1.ContainsKey(iBLane1s_tID[index])) { tCombineDict_Lane1.Add(iBLane1s_tID[index], new List()); } tCombineDict_Lane1[iBLane1s_tID[index]].Add(MF); } } vCount = iBLane2s.Count; for (int index = 0; index < vCount; index++) { bool bPrimaryNode = (iBLane2s_tID[index].node1 == iBLane2s_nID[index]); if (!bPrimaryNode && iBLane2s_tID[index].intersectionType == RoadIntersection.IntersectionTypeEnum.ThreeWay && (iBLane2s_tID[index].roadType == RoadIntersection.RoadTypeEnum.TurnLane || iBLane2s_tID[index].roadType == RoadIntersection.RoadTypeEnum.BothTurnLanes) && !iBLane2s_tID[index].isNode2BLeftTurnLane) { tUV = iBLane2s_uv[index]; tTangents = iBLane2s_tangents[index]; xMesh = tMesh_iBLanes2[index]; MF = MeshSetup2IntersectionHelper(ref xMesh, ref tUV, ref tTangents, ref road.MeshiLanes2, "LaneDA2B", basePath + "/Materials/Markers/InterLaneDisabledOuter.mat"); if (!tCombineDict_Lane2_DisabledActive.ContainsKey(iBLane2s_tID[index])) { tCombineDict_Lane2_DisabledActive.Add(iBLane2s_tID[index], new List()); } tCombineDict_Lane2_DisabledActive[iBLane2s_tID[index]].Add(MF); } else if (!bPrimaryNode && iBLane2s_tID[index].intersectionType == RoadIntersection.IntersectionTypeEnum.ThreeWay && iBLane2s_tID[index].roadType == RoadIntersection.RoadTypeEnum.BothTurnLanes && !iBLane2s_tID[index].isNode2BRightTurnLane) { tUV = iBLane2s_uv[index]; tTangents = iBLane2s_tangents[index]; xMesh = tMesh_iBLanes2[index]; MF = MeshSetup2IntersectionHelper(ref xMesh, ref tUV, ref tTangents, ref road.MeshiLanes2, "LaneDA2B", basePath + "/Materials/Markers/InterLaneDisabledOuterR.mat"); if (!tCombineDict_Lane2_DisabledActiveR.ContainsKey(iBLane2s_tID[index])) { tCombineDict_Lane2_DisabledActiveR.Add(iBLane2s_tID[index], new List()); } tCombineDict_Lane2_DisabledActiveR[iBLane2s_tID[index]].Add(MF); } else if (bPrimaryNode && iBLane2s_tID[index].intersectionType == RoadIntersection.IntersectionTypeEnum.ThreeWay && iBLane2s_tID[index].roadType == RoadIntersection.RoadTypeEnum.BothTurnLanes) { tUV = iBLane2s_uv[index]; tTangents = iBLane2s_tangents[index]; xMesh = tMesh_iBLanes2[index]; MF = MeshSetup2IntersectionHelper(ref xMesh, ref tUV, ref tTangents, ref road.MeshiLanes2, "LaneD2B", basePath + "/Materials/Markers/InterLaneDisabled.mat"); if (!tCombineDict_Lane2_Disabled.ContainsKey(iBLane2s_tID[index])) { tCombineDict_Lane2_Disabled.Add(iBLane2s_tID[index], new List()); } tCombineDict_Lane2_Disabled[iBLane2s_tID[index]].Add(MF); } else { tUV = iBLane2s_uv[index]; tTangents = iBLane2s_tangents[index]; xMesh = tMesh_iBLanes2[index]; MF = MeshSetup2IntersectionHelper(ref xMesh, ref tUV, ref tTangents, ref road.MeshiLanes2, "Lane2B", basePath + "/Materials/Markers/InterWhiteR.mat"); if (!tCombineDict_Lane2.ContainsKey(iBLane2s_tID[index])) { tCombineDict_Lane2.Add(iBLane2s_tID[index], new List()); } tCombineDict_Lane2[iBLane2s_tID[index]].Add(MF); } } vCount = iBLane3s.Count; for (int index = 0; index < vCount; index++) { bool bPrimaryNode = (iBLane3s_tID[index].node1 == iBLane3s_nID[index]); if (!bPrimaryNode && iBLane3s_tID[index].intersectionType == RoadIntersection.IntersectionTypeEnum.ThreeWay && iBLane3s_tID[index].roadType == RoadIntersection.RoadTypeEnum.BothTurnLanes && !iBLane3s_tID[index].isNode2BRightTurnLane) { tUV = iBLane3s_uv[index]; tTangents = iBLane3s_tangents[index]; xMesh = tMesh_iBLanes3[index]; MF = MeshSetup2IntersectionHelper(ref xMesh, ref tUV, ref tTangents, ref road.MeshiLanes3, "LaneD3B", basePath + "/Materials/Markers/InterLaneDisabled.mat"); if (!tCombineDict_Lane3_Disabled.ContainsKey(iBLane3s_tID[index])) { tCombineDict_Lane3_Disabled.Add(iBLane3s_tID[index], new List()); } tCombineDict_Lane3_Disabled[iBLane3s_tID[index]].Add(MF); } else { tUV = iBLane3s_uv[index]; tTangents = iBLane3s_tangents[index]; xMesh = tMesh_iBLanes3[index]; MF = MeshSetup2IntersectionHelper(ref xMesh, ref tUV, ref tTangents, ref road.MeshiLanes3, "Lane3B", basePath + "/Materials/Markers/InterWhiteR.mat"); if (!tCombineDict_Lane3.ContainsKey(iBLane3s_tID[index])) { tCombineDict_Lane3.Add(iBLane3s_tID[index], new List()); } tCombineDict_Lane3[iBLane3s_tID[index]].Add(MF); } } //Front lanes: vCount = iFLane0s.Count; for (int index = 0; index < vCount; index++) { tUV = iFLane0s_uv[index]; tTangents = iFLane0s_tangents[index]; xMesh = tMesh_iFLanes0[index]; MF = MeshSetup2IntersectionHelper(ref xMesh, ref tUV, ref tTangents, ref road.MeshiLanes0, "Lane0F", basePath + "/Materials/Markers/InterWhiteLYellowR.mat"); if (!tCombineDict_Lane0.ContainsKey(iFLane0s_tID[index])) { tCombineDict_Lane0.Add(iFLane0s_tID[index], new List()); } tCombineDict_Lane0[iFLane0s_tID[index]].Add(MF); } vCount = iFLane1s.Count; for (int index = 0; index < vCount; index++) { bool bPrimaryNode = (iFLane1s_tID[index].node1 == iFLane1s_nID[index]); if (!bPrimaryNode && iFLane1s_tID[index].intersectionType == RoadIntersection.IntersectionTypeEnum.ThreeWay && (iFLane1s_tID[index].roadType == RoadIntersection.RoadTypeEnum.BothTurnLanes || iFLane1s_tID[index].roadType == RoadIntersection.RoadTypeEnum.TurnLane) && !iFLane1s_tID[index].isNode2FLeftTurnLane) { tUV = iFLane1s_uv[index]; tTangents = iFLane1s_tangents[index]; xMesh = tMesh_iFLanes1[index]; MF = MeshSetup2IntersectionHelper(ref xMesh, ref tUV, ref tTangents, ref road.MeshiLanes1, "LaneD1F", basePath + "/Materials/Markers/InterLaneDisabled.mat"); if (!tCombineDict_Lane1_Disabled.ContainsKey(iFLane1s_tID[index])) { tCombineDict_Lane1_Disabled.Add(iFLane1s_tID[index], new List()); } tCombineDict_Lane1_Disabled[iFLane1s_tID[index]].Add(MF); } else if (bPrimaryNode && iFLane1s_tID[index].intersectionType == RoadIntersection.IntersectionTypeEnum.ThreeWay && iFLane1s_tID[index].roadType == RoadIntersection.RoadTypeEnum.BothTurnLanes) { tUV = iFLane1s_uv[index]; tTangents = iFLane1s_tangents[index]; xMesh = tMesh_iFLanes1[index]; MF = MeshSetup2IntersectionHelper(ref xMesh, ref tUV, ref tTangents, ref road.MeshiLanes1, "LaneDAR1F", basePath + "/Materials/Markers/InterLaneDisabledOuterR.mat"); if (!tCombineDict_Lane1_DisabledActive.ContainsKey(iFLane1s_tID[index])) { tCombineDict_Lane1_DisabledActive.Add(iFLane1s_tID[index], new List()); } tCombineDict_Lane1_DisabledActive[iFLane1s_tID[index]].Add(MF); } else { tUV = iFLane1s_uv[index]; tTangents = iFLane1s_tangents[index]; xMesh = tMesh_iFLanes1[index]; MF = MeshSetup2IntersectionHelper(ref xMesh, ref tUV, ref tTangents, ref road.MeshiLanes1, "Lane1F", basePath + "/Materials/Markers/InterYellowLWhiteR.mat"); if (!tCombineDict_Lane1.ContainsKey(iFLane1s_tID[index])) { tCombineDict_Lane1.Add(iFLane1s_tID[index], new List()); } tCombineDict_Lane1[iFLane1s_tID[index]].Add(MF); } } vCount = iFLane2s.Count; for (int index = 0; index < vCount; index++) { bool bPrimaryNode = (iFLane2s_tID[index].node1 == iFLane2s_nID[index]); if (!bPrimaryNode && iFLane2s_tID[index].intersectionType == RoadIntersection.IntersectionTypeEnum.ThreeWay && (iFLane2s_tID[index].roadType == RoadIntersection.RoadTypeEnum.BothTurnLanes || iFLane2s_tID[index].roadType == RoadIntersection.RoadTypeEnum.TurnLane) && !iFLane2s_tID[index].isNode2FLeftTurnLane) { tUV = iFLane2s_uv[index]; tTangents = iFLane2s_tangents[index]; xMesh = tMesh_iFLanes2[index]; MF = MeshSetup2IntersectionHelper(ref xMesh, ref tUV, ref tTangents, ref road.MeshiLanes2, "LaneDA2F", basePath + "/Materials/Markers/InterLaneDisabledOuter.mat"); if (!tCombineDict_Lane2_DisabledActive.ContainsKey(iFLane2s_tID[index])) { tCombineDict_Lane2_DisabledActive.Add(iFLane2s_tID[index], new List()); } tCombineDict_Lane2_DisabledActive[iFLane2s_tID[index]].Add(MF); } else if (!bPrimaryNode && iFLane2s_tID[index].intersectionType == RoadIntersection.IntersectionTypeEnum.ThreeWay && iFLane2s_tID[index].roadType == RoadIntersection.RoadTypeEnum.BothTurnLanes && !iFLane2s_tID[index].isNode2FRightTurnLane) { tUV = iFLane2s_uv[index]; tTangents = iFLane2s_tangents[index]; xMesh = tMesh_iFLanes2[index]; MF = MeshSetup2IntersectionHelper(ref xMesh, ref tUV, ref tTangents, ref road.MeshiLanes2, "LaneDAR2F", basePath + "/Materials/Markers/InterLaneDisabledOuterR.mat"); if (!tCombineDict_Lane2_DisabledActiveR.ContainsKey(iFLane2s_tID[index])) { tCombineDict_Lane2_DisabledActiveR.Add(iFLane2s_tID[index], new List()); } tCombineDict_Lane2_DisabledActiveR[iFLane2s_tID[index]].Add(MF); } else if (bPrimaryNode && iFLane2s_tID[index].intersectionType == RoadIntersection.IntersectionTypeEnum.ThreeWay && iFLane2s_tID[index].roadType == RoadIntersection.RoadTypeEnum.BothTurnLanes) { tUV = iFLane2s_uv[index]; tTangents = iFLane2s_tangents[index]; xMesh = tMesh_iFLanes2[index]; MF = MeshSetup2IntersectionHelper(ref xMesh, ref tUV, ref tTangents, ref road.MeshiLanes2, "LaneD2F", basePath + "/Materials/Markers/InterLaneDisabled.mat"); if (!tCombineDict_Lane2_Disabled.ContainsKey(iFLane2s_tID[index])) { tCombineDict_Lane2_Disabled.Add(iFLane2s_tID[index], new List()); } tCombineDict_Lane2_Disabled[iFLane2s_tID[index]].Add(MF); } else { tUV = iFLane2s_uv[index]; tTangents = iFLane2s_tangents[index]; xMesh = tMesh_iFLanes2[index]; MF = MeshSetup2IntersectionHelper(ref xMesh, ref tUV, ref tTangents, ref road.MeshiLanes2, "Lane2F", basePath + "/Materials/Markers/InterWhiteR.mat"); if (!tCombineDict_Lane2.ContainsKey(iFLane2s_tID[index])) { tCombineDict_Lane2.Add(iFLane2s_tID[index], new List()); } tCombineDict_Lane2[iFLane2s_tID[index]].Add(MF); } } vCount = iFLane3s.Count; for (int index = 0; index < vCount; index++) { bool bPrimaryNode = (iFLane3s_tID[index].node1 == iFLane3s_nID[index]); if (!bPrimaryNode && iFLane3s_tID[index].intersectionType == RoadIntersection.IntersectionTypeEnum.ThreeWay && iFLane3s_tID[index].roadType == RoadIntersection.RoadTypeEnum.BothTurnLanes && !iFLane3s_tID[index].isNode2FRightTurnLane) { tUV = iFLane3s_uv[index]; tTangents = iFLane3s_tangents[index]; xMesh = tMesh_iFLanes3[index]; MF = MeshSetup2IntersectionHelper(ref xMesh, ref tUV, ref tTangents, ref road.MeshiLanes3, "LaneD3F", basePath + "/Materials/Markers/InterWhiteR.mat"); if (!tCombineDict_Lane3_Disabled.ContainsKey(iFLane3s_tID[index])) { tCombineDict_Lane3_Disabled.Add(iFLane3s_tID[index], new List()); } tCombineDict_Lane3_Disabled[iFLane3s_tID[index]].Add(MF); } else { tUV = iFLane3s_uv[index]; tTangents = iFLane3s_tangents[index]; xMesh = tMesh_iFLanes3[index]; MF = MeshSetup2IntersectionHelper(ref xMesh, ref tUV, ref tTangents, ref road.MeshiLanes3, "Lane3F", basePath + "/Materials/Markers/InterWhiteR.mat"); if (!tCombineDict_Lane3.ContainsKey(iFLane3s_tID[index])) { tCombineDict_Lane3.Add(iFLane3s_tID[index], new List()); } tCombineDict_Lane3[iFLane3s_tID[index]].Add(MF); } } //Main plates: vCount = iBMainPlates.Count; for (int index = 0; index < vCount; index++) { tUV = iBMainPlates_uv[index]; tTangents = iBMainPlates_tangents[index]; xMesh = tMesh_iBMainPlates[index]; MF = MeshSetup2IntersectionHelper(ref xMesh, ref tUV, ref tTangents, ref road.MeshiMainPlates, "MainPlateB", basePath + "/Materials/Road1.mat", false); if (!tCombineDict_MainPlate.ContainsKey(iBMainPlates_tID[index])) { tCombineDict_MainPlate.Add(iBMainPlates_tID[index], new List()); } tCombineDict_MainPlate[iBMainPlates_tID[index]].Add(MF); Mesh fMesh = new Mesh(); fMesh.vertices = iBMainPlates[index]; fMesh.triangles = iBMainPlates_tris[index]; fMesh.normals = iBMainPlates_normals[index]; tUV = iBMainPlates_uv2[index]; tTangents = iBMainPlates_tangents2[index]; MF = MeshSetup2IntersectionHelper(ref fMesh, ref tUV, ref tTangents, ref road.MeshiMainPlates, "MainPlateBM", basePath + "/Materials/InterMainPlate1.mat"); if (!tCombineDict_MainPlateM.ContainsKey(iBMainPlates_tID[index])) { tCombineDict_MainPlateM.Add(iBMainPlates_tID[index], new List()); } tCombineDict_MainPlateM[iBMainPlates_tID[index]].Add(MF); } vCount = iFMainPlates.Count; for (int index = 0; index < vCount; index++) { tUV = iFMainPlates_uv[index]; tTangents = iFMainPlates_tangents[index]; xMesh = tMesh_iFMainPlates[index]; MF = MeshSetup2IntersectionHelper(ref xMesh, ref tUV, ref tTangents, ref road.MeshiMainPlates, "MainPlateFM", basePath + "/Materials/Road1.mat", false); if (!tCombineDict_MainPlate.ContainsKey(iFMainPlates_tID[index])) { tCombineDict_MainPlate.Add(iFMainPlates_tID[index], new List()); } tCombineDict_MainPlate[iFMainPlates_tID[index]].Add(MF); Mesh tMesh = new Mesh(); tMesh.vertices = iFMainPlates[index]; tMesh.triangles = iFMainPlates_tris[index]; tMesh.normals = iFMainPlates_normals[index]; tUV = iFMainPlates_uv2[index]; tTangents = iFMainPlates_tangents2[index]; MF = MeshSetup2IntersectionHelper(ref tMesh, ref tUV, ref tTangents, ref road.MeshiMainPlates, "MainPlateFM", basePath + "/Materials/InterMainPlate1.mat"); if (!tCombineDict_MainPlateM.ContainsKey(iFMainPlates_tID[index])) { tCombineDict_MainPlateM.Add(iFMainPlates_tID[index], new List()); } tCombineDict_MainPlateM[iFMainPlates_tID[index]].Add(MF); } vCount = road.spline.GetNodeCount(); SplineN tNode = null; for (int index = 0; index < vCount; index++) { tNode = road.spline.nodes[index]; if (tNode.isIntersection && tNode.intersection != null && tNode.intersection.node1 == tNode) { //Create center plate Vector3[] xVerts = new Vector3[4]; xVerts[0] = tNode.intersection.cornerLR; xVerts[1] = tNode.intersection.cornerRR; xVerts[2] = tNode.intersection.cornerLL; xVerts[3] = tNode.intersection.cornerRL; int[] xTris = new int[6]; xTris[0] = 0; xTris[1] = 2; xTris[2] = 1; xTris[3] = 2; xTris[4] = 3; xTris[5] = 1; Vector2[] xUV = new Vector2[4]; xUV[0] = new Vector2(xVerts[0].x / 5f, xVerts[0].z / 5f); xUV[1] = new Vector2(xVerts[1].x / 5f, xVerts[1].z / 5f); xUV[2] = new Vector2(xVerts[2].x / 5f, xVerts[2].z / 5f); xUV[3] = new Vector2(xVerts[3].x / 5f, xVerts[3].z / 5f); Vector2[] xUV2 = new Vector2[4]; xUV2[0] = new Vector2(0f, 0f); xUV2[1] = new Vector2(1f, 0f); xUV2[2] = new Vector2(0f, 1f); xUV2[3] = new Vector2(1f, 1f); Mesh vMesh = new Mesh(); vMesh.vertices = xVerts; vMesh.triangles = xTris; vMesh.normals = new Vector3[4]; vMesh.uv = xUV; vMesh.RecalculateBounds(); vMesh.RecalculateNormals(); vMesh.tangents = RootUtils.ProcessTangents(xTris, vMesh.normals, xUV, xVerts); if (road.isLightmapped) { //EngineIntegration.GenerateSecondaryUVSet(vMesh); } Transform intersectionChild; int cCount = tNode.intersection.transform.childCount - 1; for (int j = cCount; j >= 0; j--) { intersectionChild = tNode.intersection.transform.GetChild(j); if (intersectionChild.name.ToLower() == "tcenter") { Object.DestroyImmediate(intersectionChild.gameObject); continue; } if (intersectionChild.name.ToLower() == "markcenter") { Object.DestroyImmediate(intersectionChild.gameObject); } } GameObject tCenter = new GameObject("tCenter"); MF = tCenter.AddComponent(); MF.sharedMesh = vMesh; tCenter.transform.parent = tNode.intersection.transform; if (road.isLightmapped) { EngineIntegration.SetStaticEditorFlags(tCenter); } if (road.isStatic) { tCenter.isStatic = true; } Mesh mMesh = new Mesh(); Vector3[] bVerts = new Vector3[4]; mMesh.vertices = xVerts; mMesh.triangles = xTris; mMesh.normals = new Vector3[4]; mMesh.uv = xUV2; mMesh.RecalculateBounds(); mMesh.RecalculateNormals(); mMesh.tangents = RootUtils.ProcessTangents(xTris, vMesh.normals, xUV, xVerts); GameObject tMarker = new GameObject("CenterMarkers"); //tMarker.transform.localPosition = default(Vector3); MF = tMarker.AddComponent(); MF.sharedMesh = mMesh; MeshRenderer MR = tMarker.AddComponent(); MR.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off; //if(tNode.roadIntersection.MarkerCenter != null) //{ //// MR.material = tNode.roadIntersection.MarkerCenter; //} tMarker.transform.parent = tNode.intersection.transform; if (road.isLightmapped) { EngineIntegration.SetStaticEditorFlags(tMarker); } if (road.isStatic) { tMarker.isStatic = true; } bVerts = MF.sharedMesh.vertices; for (int j = 0; j < 4; j++) { bVerts[j].y = tNode.intersection.signHeight; } int zCount = bVerts.Length; for (int z = 0; z < zCount; z++) { bVerts[z] -= tNode.transform.position; } MF.sharedMesh.vertices = bVerts; MR.transform.position = tNode.intersection.transform.position; mMesh.RecalculateBounds(); if (road.isLightmapped) { //EngineIntegration.GenerateSecondaryUVSet(mMesh); } SaveMesh(SaveMeshTypeEnum.Intersection, MF.sharedMesh, road, tNode.intersection.transform.name + "-" + "CenterMarkers"); } } foreach (KeyValuePair> KVP in tCombineDict_Lane0) { if (!uniqueRoadIntersection.Contains(KVP.Key)) { uniqueRoadIntersection.Add(KVP.Key); } MeshSetup2CombineIntersections(KVP, KVP.Key.transform.name + "-" + "Lane0"); } foreach (KeyValuePair> KVP in tCombineDict_Lane1) { if (!uniqueRoadIntersection.Contains(KVP.Key)) { uniqueRoadIntersection.Add(KVP.Key); } MeshSetup2CombineIntersections(KVP, KVP.Key.transform.name + "-" + "Lane1"); } foreach (KeyValuePair> KVP in tCombineDict_Lane2) { if (!uniqueRoadIntersection.Contains(KVP.Key)) { uniqueRoadIntersection.Add(KVP.Key); } MeshSetup2CombineIntersections(KVP, KVP.Key.transform.name + "-" + "Lane2"); } foreach (KeyValuePair> KVP in tCombineDict_Lane3) { if (!uniqueRoadIntersection.Contains(KVP.Key)) { uniqueRoadIntersection.Add(KVP.Key); } MeshSetup2CombineIntersections(KVP, KVP.Key.transform.name + "-" + "Lane3"); } foreach (KeyValuePair> KVP in tCombineDict_MainPlate) { if (!uniqueRoadIntersection.Contains(KVP.Key)) { uniqueRoadIntersection.Add(KVP.Key); } MeshSetup2CombineIntersections(KVP, KVP.Key.transform.name + "-" + "TiledExt", true); } foreach (KeyValuePair> KVP in tCombineDict_MainPlateM) { if (!uniqueRoadIntersection.Contains(KVP.Key)) { uniqueRoadIntersection.Add(KVP.Key); } MeshSetup2CombineIntersections(KVP, KVP.Key.transform.name + "-" + "StretchExt"); } foreach (KeyValuePair> KVP in tCombineDict_Lane1_Disabled) { if (!uniqueRoadIntersection.Contains(KVP.Key)) { uniqueRoadIntersection.Add(KVP.Key); } MeshSetup2CombineIntersections(KVP, KVP.Key.transform.name + "-" + "LaneD1"); } foreach (KeyValuePair> KVP in tCombineDict_Lane3_Disabled) { if (!uniqueRoadIntersection.Contains(KVP.Key)) { uniqueRoadIntersection.Add(KVP.Key); } MeshSetup2CombineIntersections(KVP, KVP.Key.transform.name + "-" + "LaneD3"); } foreach (KeyValuePair> KVP in tCombineDict_Lane2_DisabledActive) { if (!uniqueRoadIntersection.Contains(KVP.Key)) { uniqueRoadIntersection.Add(KVP.Key); } MeshSetup2CombineIntersections(KVP, KVP.Key.transform.name + "-" + "LaneDA2"); } foreach (KeyValuePair> KVP in tCombineDict_Lane2_DisabledActiveR) { if (!uniqueRoadIntersection.Contains(KVP.Key)) { uniqueRoadIntersection.Add(KVP.Key); } MeshSetup2CombineIntersections(KVP, KVP.Key.transform.name + "-" + "LaneDAR2"); } foreach (KeyValuePair> KVP in tCombineDict_Lane2_Disabled) { if (!uniqueRoadIntersection.Contains(KVP.Key)) { uniqueRoadIntersection.Add(KVP.Key); } MeshSetup2CombineIntersections(KVP, KVP.Key.transform.name + "-" + "LaneD2"); } foreach (KeyValuePair> KVP in tCombineDict_Lane1_DisabledActive) { if (!uniqueRoadIntersection.Contains(KVP.Key)) { uniqueRoadIntersection.Add(KVP.Key); } MeshSetup2CombineIntersections(KVP, KVP.Key.transform.name + "-" + "LaneDA1"); } foreach (RoadIntersection roadIntersection in uniqueRoadIntersection) { roadIntersection.UpdateMaterials(); } } /// Combines all intersections in _valuePair into an single mesh private void MeshSetup2CombineIntersections(KeyValuePair> _valuePair, string _name, bool _isMainPlates = false) { int vCount = _valuePair.Value.Count; if (vCount < 1) { return; } _name = road.name + "-" + _name; Transform child; GameObject tCenter = null; int cCount = _valuePair.Key.transform.childCount - 1; for (int index = cCount; index >= 0; index--) { child = _valuePair.Key.transform.GetChild(index); if (child.name.ToLower() == _name.ToLower()) { Object.DestroyImmediate(child.gameObject); continue; } if (_isMainPlates && child.name.ToLower() == "tcenter") { tCenter = child.gameObject; } } int CombineCount = vCount; if (tCenter != null) { CombineCount += 1; } CombineInstance[] combine = new CombineInstance[CombineCount]; for (int index = 0; index < vCount; index++) { combine[index].mesh = _valuePair.Value[index].sharedMesh; combine[index].transform = _valuePair.Value[index].transform.localToWorldMatrix; } int SpecialVertCount = 0; if (tCenter != null) { for (int index = 0; index < (CombineCount - 1); index++) { SpecialVertCount += combine[index].mesh.vertexCount; } MeshFilter tMF = tCenter.GetComponent(); Vector3[] xVerts = tMF.sharedMesh.vertices; float xHeight = combine[0].mesh.vertices[combine[0].mesh.vertexCount - 1].y; for (int index = 0; index < xVerts.Length; index++) { xVerts[index].y = xHeight; } tMF.sharedMesh.vertices = xVerts; combine[CombineCount - 1].mesh = tMF.sharedMesh; combine[CombineCount - 1].transform = tMF.transform.localToWorldMatrix; } GameObject tObj = new GameObject(_name); MeshFilter MF = tObj.AddComponent(); Mesh tMesh = new Mesh(); tMesh.CombineMeshes(combine); MF.sharedMesh = tMesh; MeshRenderer MR = tObj.AddComponent(); MR.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off; tObj.transform.parent = _valuePair.Key.transform; Vector3[] tVerts = MF.sharedMesh.vertices; Vector3 tVect = tObj.transform.localPosition; for (int index = 0; index < tVerts.Length; index++) { tVerts[index] += tVect; if (_name.ToLower().EndsWith("-stretchext")) { tVerts[index] += new Vector3(0f, 0.01f); } } MF.sharedMesh.vertices = tVerts; tObj.transform.localPosition = new Vector3(0f, 0f, 0f); MF.sharedMesh.RecalculateBounds(); MF.sharedMesh.RecalculateNormals(); MF.sharedMesh.tangents = RootUtils.ProcessTangents(MF.sharedMesh.triangles, MF.sharedMesh.normals, MF.sharedMesh.uv, MF.sharedMesh.vertices); if (road.isLightmapped) { EngineIntegration.GenerateSecondaryUVSet(MF.sharedMesh); EngineIntegration.SetStaticEditorFlags(tObj); } if (road.isStatic) { tObj.isStatic = true; } if (_isMainPlates) { MeshCollider MC = tObj.AddComponent(); MC.sharedMesh = MF.sharedMesh; MC.material = road.RoadPhysicMaterial; MC.material.name = MC.material.name.Replace(" (Instance)", ""); Object.DestroyImmediate(tCenter); } SaveMesh(SaveMeshTypeEnum.Intersection, MF.sharedMesh, road, _name); } /// Assigns values to _mesh and returns the MeshFilter of a new GO private MeshFilter MeshSetup2IntersectionHelper(ref Mesh _mesh, ref Vector2[] _uv, ref Vector4[] _tangents, ref GameObject _masterObj, string _name, string _mat, bool _isCollider = false) { if (_mesh == null) { return null; } _mesh.uv = _uv; _mesh.tangents = _tangents; if (road.isLightmapped) { EngineIntegration.GenerateSecondaryUVSet(_mesh); } GameObject tObj = new GameObject(_name); tObj.transform.parent = _masterObj.transform; MeshFilter MF = tObj.AddComponent(); MF.sharedMesh = _mesh; if (_isCollider) { MeshCollider MC = tObj.AddComponent(); MC.sharedMesh = MF.sharedMesh; } if (_mat.Length < 1) { return null; } MeshRenderer MR = tObj.AddComponent(); MR.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off; RoadEditorUtility.SetRoadMaterial(_mat, MR); if (road.isLightmapped) { EngineIntegration.SetStaticEditorFlags(tObj); } if (road.isStatic) { tObj.isStatic = true; } return MF; } #endregion /// Assigns values to _mesh private Mesh MeshSetup2Helper(ref Mesh _mesh, Vector2[] _uv, Vector4[] _tangents, ref GameObject _obj, Material[] _shoulderMaterials, Material[] _markerMaterials, Material[] _roadMaterials, bool _isMarker, bool _isShoulder = false, bool _isBridge = false) { _mesh.uv = _uv; _mesh.tangents = _tangents; if (road.isLightmapped) { EngineIntegration.GenerateSecondaryUVSet(_mesh); } MeshFilter MF = _obj.AddComponent(); MF.sharedMesh = _mesh; MeshCollider MC = null; if (road.isUsingMeshColliders) { MC = _obj.AddComponent(); MC.sharedMesh = MF.sharedMesh; } MeshRenderer MR = _obj.AddComponent(); if (_isShoulder) { if (_shoulderMaterials.Length > 0) { MR.materials = _shoulderMaterials; } } else { if (_isMarker) { // It should not be necessary to check this, but I let it until I'm sure this does not break anything. if (_markerMaterials.Length > 0) { MR.materials = _markerMaterials; } } else { if (_roadMaterials.Length > 0) { MR.materials = _roadMaterials; } if (MC) { MC.sharedMaterial = road.RoadPhysicMaterial; } } } if (road.isLightmapped) { EngineIntegration.SetStaticEditorFlags(_obj); } if (road.isStatic) { _obj.isStatic = true; } return _mesh; } /// Creates a GameObject and adds mesh collider / renderer and configures mesh to be static etc. private bool MeshSetup2HelperRoadCuts(int _i, ref Mesh _mesh, Vector2[] _uv, Vector4[] _tangents, ref GameObject _masterObj, bool _isMarkers, out GameObject _createdObj, Material[] _markerMaterials, Material[] _roadMaterials) { if (!_isMarkers) { _createdObj = new GameObject("RoadCut" + _i.ToString()); RoadCutNodes[_i].roadCutWorld = _createdObj; } else { _createdObj = new GameObject("Markers" + _i.ToString()); RoadCutNodes[_i].roadCutMarker = _createdObj; } _createdObj.transform.position = cut_RoadVectorsHome[_i]; _mesh.uv = _uv; _mesh.tangents = _tangents; if (road.isLightmapped) { EngineIntegration.GenerateSecondaryUVSet(_mesh); } MeshFilter MF = _createdObj.AddComponent(); MF.sharedMesh = _mesh; MeshCollider MC = null; if (road.isUsingMeshColliders && !_isMarkers) { MC = _createdObj.AddComponent(); if (MC.sharedMesh == null) { MC.sharedMesh = MF.sharedMesh; } } MeshRenderer MR = _createdObj.AddComponent(); //Disable shadows for road cuts and markers: MR.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off; bool isUsingMaterials = false; //Apply Materials: if (_isMarkers) { if (_markerMaterials.Length > 0) { MR.materials = _markerMaterials; isUsingMaterials = true; } } else { if (_roadMaterials.Length > 0) { MR.materials = _roadMaterials; isUsingMaterials = true; } } _createdObj.transform.parent = _masterObj.transform; if (!_isMarkers && MC != null) { MC.sharedMaterial = road.RoadPhysicMaterial; } if (road.isLightmapped) { EngineIntegration.SetStaticEditorFlags(_createdObj); } if (road.isStatic) { _createdObj.isStatic = true; } return isUsingMaterials; } /// Inserts new GO into according shoulder collection at _i; Assigns values to _mesh private bool MeshSetup2HelperCutsShoulder(int _i, ref Mesh _mesh, Vector2[] _uv, Vector4[] _tangents, ref GameObject _masterObj, bool _isLeft, bool _isMarkers, out GameObject _createdObj, Material[] _shoulderMarkerMaterials, Material[] _shoulderMaterials) { if (_isMarkers) { _createdObj = new GameObject("Markers" + _i.ToString()); if (_isLeft) { _createdObj.transform.position = cut_ShoulderL_VectorsHome[_i]; ShoulderCutsLNodes[_i].shoulderCutLMarker = _createdObj; } else { _createdObj.transform.position = cut_ShoulderR_VectorsHome[_i]; ShoulderCutsRNodes[_i].shoulderCutRMarker = _createdObj; } } else { if (_isLeft) { _createdObj = new GameObject("SCutL" + _i.ToString()); _createdObj.transform.position = cut_ShoulderL_VectorsHome[_i]; ShoulderCutsLNodes[_i].shoulderCutLWorld = _createdObj; } else { _createdObj = new GameObject("SCutR" + _i.ToString()); _createdObj.transform.position = cut_ShoulderR_VectorsHome[_i]; ShoulderCutsRNodes[_i].shoulderCutRWorld = _createdObj; } } MeshCollider MC = null; if (road.isUsingMeshColliders) { MC = _createdObj.AddComponent(); } _mesh.uv = _uv; _mesh.tangents = _tangents; if (road.isLightmapped) { EngineIntegration.GenerateSecondaryUVSet(_mesh); } MeshFilter MF = _createdObj.AddComponent(); MF.sharedMesh = _mesh; if (road.isUsingMeshColliders) { if (MC.sharedMesh == null) { MC.sharedMesh = MF.sharedMesh; } } bool bHasMats = false; //Disable shadows for road cuts and markers: MeshRenderer MR = _createdObj.AddComponent(); MR.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off; if (_isMarkers) { if (_shoulderMarkerMaterials.Length > 0) { MR.materials = _shoulderMarkerMaterials; bHasMats = true; } } else { if (_shoulderMaterials.Length > 0) { MR.materials = _shoulderMaterials; MR = null; bHasMats = true; } } if (!_isMarkers && MC != null) { MC.sharedMaterial = road.ShoulderPhysicMaterial; } _createdObj.transform.parent = _masterObj.transform; if (road.isLightmapped) { EngineIntegration.SetStaticEditorFlags(_createdObj); } if (road.isStatic) { _createdObj.isStatic = true; } MF = null; MC = null; return bHasMats; } #endregion /// Saves Mesh as an asset private static void SaveMesh(SaveMeshTypeEnum _saveType, Mesh _mesh, Road _road, string _name) { if (!_road.isSavingMeshes) { return; } string sceneName; sceneName = UnityEngine.SceneManagement.SceneManager.GetActiveScene().name; sceneName = sceneName.Replace("/", ""); sceneName = sceneName.Replace(".", ""); string folderName = Path.Combine(RoadEditorUtility.GetBasePath(), "Mesh"); folderName = Path.Combine(folderName, "Generated"); if (_saveType == SaveMeshTypeEnum.Road) { folderName = Path.Combine(folderName, "Roads"); } else if (_saveType == SaveMeshTypeEnum.Shoulder) { folderName = Path.Combine(folderName, "Shoulders"); } else if (_saveType == SaveMeshTypeEnum.Intersection) { folderName = Path.Combine(folderName, "Intersections"); } else if (_saveType == SaveMeshTypeEnum.Railing) { folderName = Path.Combine(folderName, "Railings"); } else if (_saveType == SaveMeshTypeEnum.Center) { folderName = Path.Combine(folderName, "CenterDividers"); } else if (_saveType == SaveMeshTypeEnum.RoadCut) { folderName = Path.Combine(Path.Combine(folderName, "Roads"), "Cuts"); } else if (_saveType == SaveMeshTypeEnum.SCut) { folderName = Path.Combine(Path.Combine(folderName, "Shoulders"), "Cuts"); } else if (_saveType == SaveMeshTypeEnum.RoadConn) { folderName = Path.Combine(folderName, "RoadConn"); } string path = Path.GetDirectoryName(Application.dataPath); path = Path.Combine(path, folderName); if (!System.IO.Directory.Exists(path)) { System.IO.Directory.CreateDirectory(path); } string roadName = _road.transform.name; string finalName = Path.Combine(folderName, sceneName + "-" + roadName + "-" + _name + ".asset"); if (_saveType == SaveMeshTypeEnum.Intersection) { finalName = Path.Combine(folderName, sceneName + "-" + _name + ".asset"); } finalName = EngineIntegration.GetUnityFilePath(finalName); EngineIntegration.CreateAsset(_mesh, finalName); } } }