private Vector3 CoordinateForRoadWithAbstractRoadInfos(Intersection intersection, Road connectedRoad, RightOrLeft rtlt, AbstractWayInfo[] infos) { infos = AbstractWayInfo.sortAbstractWayInfos(infos); // convert the road to an abstract way info AbstractWayInfo info = new AbstractWayInfo(IntersectionMath.getOutgoingVector(intersection, connectedRoad).normalized, connectedRoad.GetRoadWidth()); // TODO : CHECK FOR nonexistent index int index = 0; for (int i = 0; i < infos.Length; i++) { if (infos[i] == info) { index = i; } } Vector3[] vertices = MeshVerticesForAbstractWayInfos(infos); switch (rtlt) { case RightOrLeft.LEFT: return(vertices[index - 1 < 0 ? infos.Length - 1 : index - 1]); case RightOrLeft.RIGHT: return(vertices[index]); } Debug.LogError("Semantics Error, please check"); return(Vector3.zero); }
private GameObject buildMultiwayIntersectionWithVectors(Intersection intersection, AbstractWayInfo[] outgoingWays) { // sort vectors according to orientations first AbstractWayInfo[] sorted = AbstractWayInfo.sortAbstractWayInfos(outgoingWays); Mesh mesh = new Mesh(); var vertices = MeshVerticesForAbstractWayInfos(sorted); mesh.vertices = vertices; int[] triangles = new int[outgoingWays.Length * 3]; // TODO : Figure out how sortBy works, thus affecting the orientation of the plane for (int i = 0; i < sorted.Length; i++) { triangles [i * 3 + 2] = i; triangles [i * 3 + 1] = sorted.Length + 1; triangles [i * 3 + 0] = i + 1; } mesh.triangles = triangles; Vector2[] uv = new Vector2[vertices.Length]; for (int i = 0; i < sorted.Length + 1; i++) { switch (i % 4) { case 0: uv [i] = new Vector2(0, 0); break; case 1: uv [i] = new Vector2(0, 1); break; case 2: uv [i] = new Vector2(1, 1); break; case 3: uv [i] = new Vector2(1, 0); break; } } uv [sorted.Length + 1] = new Vector2(0.5f, 0.5f); mesh.uv = uv; Vector3[] normals = new Vector3[uv.Length]; for (int i = 0; i < normals.Length; i++) { normals [i] = Vector3.up; } mesh.normals = normals; var intersectionObj = createGameObjectWithPrefabPositionAndMesh(fourWayIntersectionPrefab, intersection.position, mesh, intersection.customization); return(intersectionObj); }
static public AbstractWayInfo[] InfosWithDirectionsAndWidths(Vector3[] vecs, float[] roadWidths) { var numElems = vecs.Length <= roadWidths.Length ? vecs.Length : roadWidths.Length; AbstractWayInfo[] infos = new AbstractWayInfo[numElems]; for (int i = 0; i < numElems; i++) { infos [i] = new AbstractWayInfo(vecs [i], roadWidths [i]); } return(infos); }
// get intersection of rd1's right edge with rd2's left edge private Vector3 CoordinateOfIntersectionBetweenTwoWays(AbstractWayInfo rd1, AbstractWayInfo rd2) { Vector3 coordinateRes; Vector3 vec1 = rd1.direction.normalized; Vector3 vec2 = rd2.direction.normalized; Vector3 vec1Norm = Quaternion.Euler(new Vector3(0, 90, 0)) * vec1 * rd1.roadWidth / 2; Vector3 vec2Norm = Quaternion.Euler(new Vector3(0, -90, 0)) * vec2 * rd2.roadWidth / 2; bool res = Math3d.LineLineIntersection(out coordinateRes, vec1Norm, vec1, vec2Norm, vec2); return(coordinateRes); }
/** * Assume the input vertices are sorted, */ private Vector3[] MeshVerticesForAbstractWayInfos(AbstractWayInfo[] sorted) { // get a list of intersection vertices Vector3[] vertices = new Vector3[sorted.Length + 2]; for (int i = 0; i < sorted.Length; i++) { AbstractWayInfo rd1 = sorted[i]; AbstractWayInfo rd2 = sorted[(i + 1) % sorted.Length]; vertices[i] = CoordinateOfIntersectionBetweenTwoWays(rd1, rd2); //Debug.LogFormat("vec1 = {2}, vec2 = {3}, Vertex ({0}) : {1}", i, vertices[i], rd1.direction, rd2.direction); } vertices[sorted.Length] = vertices[0]; // the second last vertex is the first (for UV) vertices[sorted.Length + 1] = Vector3.zero; // the last vertex is the intersection center //Debug.LogFormat("Vertex ({0}) : {1}", sorted.Length, vertices[sorted.Length]); return(vertices); }
private AbstractWayInfo[] AbstractWayInfosForMultiwayIntersection(Intersection intersection, Road[] connectedRoads) { // convert roads to vectos Vector3[] vectors = connectedRoads.Select(rd => IntersectionMath.getOutgoingVector(intersection, rd)).ToArray(); float[] widths = connectedRoads.Select(rd => rd.GetRoadWidth()).ToArray(); AbstractWayInfo[] infos; // handle when connectedRoads.Length == 3 << build a four-way intersection instead if (connectedRoads.Length == 3) { // find the vector whose direction is of greatest difference to other two Vector3 maxVector = vectors[0]; float maxRoadWidth = widths[0]; float maxAngles = 0; for (int i = 0; i < 3; i++) { float accum = 0; for (int j = 0; j < 3; j++) { float zeroTo180Angle = Vector3.Angle(vectors[i], vectors[j]); float distance = zeroTo180Angle > 90 ? 180 - zeroTo180Angle : zeroTo180Angle; accum += distance; } if (accum > maxAngles) { maxVector = vectors[i]; maxRoadWidth = widths[i]; maxAngles = accum; } } Vector3[] resultingVectors = { vectors[0], vectors[1], vectors[2], -maxVector }; float[] resultingWidths = { widths[0], widths[1], widths[2], maxRoadWidth }; infos = AbstractWayInfo.InfosWithDirectionsAndWidths(resultingVectors, resultingWidths); } else { infos = AbstractWayInfo.InfosWithDirectionsAndWidths(vectors, widths); } return(infos); }
private AbstractWayInfo[] AbstractWayInfosForTwoWayIntersection(Intersection intersection, Road road1, Road road2) { Vector3 vec1 = IntersectionMath.getOutgoingVector(intersection, road1).normalized; Vector3 vec2 = IntersectionMath.getOutgoingVector(intersection, road2).normalized; // create a four way intersection instead of a two way intersection if the angle is less than 90 Vector3[] vecs = null; float[] roadWidths = null; switch (GetTwoWayIntersectionType(intersection)) { case TwoWayIntersectionType.SKEW: vecs = new[] { vec1, vec2, -vec1, -vec2 }; roadWidths = new[] { road1.GetRoadWidth(), road2.GetRoadWidth(), road1.GetRoadWidth(), road2.GetRoadWidth() }; break; case TwoWayIntersectionType.TRANSITION: // create a halfway rotation Quaternion rotation = Quaternion.Euler(Quaternion.FromToRotation(vec1, vec2).eulerAngles / 2); // this is the virtual directional vector Vector3 newVec = rotation * vec1; // this is the virtual road width, set it to be the average of the two float newWidth = road1.GetRoadWidth() + road2.GetRoadWidth() / 2; vecs = new[] { vec1, vec2, newVec, -newVec }; roadWidths = new[] { road1.GetRoadWidth(), road2.GetRoadWidth(), newWidth, newWidth }; break; case TwoWayIntersectionType.SMOOTH: Debug.LogError("Code Error, this method is to be called without smooth transition"); break; } // zip vecs and roadWidths into abstract road infos AbstractWayInfo[] infos = AbstractWayInfo.InfosWithDirectionsAndWidths(vecs, roadWidths); return(infos); }