void OnSceneGUI() { IntersectionTester tester = (IntersectionTester)target; float handleSize = HandleUtility.GetHandleSize((Vector3)tester.v0) / 8.0f; tester.v0 = Handles.Slider2D(tester.v0, Vector3.up, Vector3.right, Vector3.forward, handleSize, Handles.SphereCap, new Vector2(0.1f, 0.1f)); tester.v1 = Handles.Slider2D(tester.v1, Vector3.up, Vector3.right, Vector3.forward, handleSize, Handles.SphereCap, new Vector2(0.1f, 0.1f)); tester.v2 = Handles.Slider2D(tester.v2, Vector3.up, Vector3.right, Vector3.forward, handleSize, Handles.SphereCap, new Vector2(0.1f, 0.1f)); tester.v3 = Handles.Slider2D(tester.v3, Vector3.up, Vector3.right, Vector3.forward, handleSize, Handles.SphereCap, new Vector2(0.1f, 0.1f)); tester.v4 = Handles.Slider2D(tester.v4, Vector3.up, Vector3.right, Vector3.forward, handleSize, Handles.SphereCap, new Vector2(0.1f, 0.1f)); Vector2 altV0 = new Vector2(tester.v0.x, tester.v0.z); Vector2 altV1 = new Vector2(tester.v1.x, tester.v1.z); Vector2 altV2 = new Vector2(tester.v2.x, tester.v2.z); Vector2 altV3 = new Vector2(tester.v3.x, tester.v3.z); Vector2 altV4 = new Vector2(tester.v4.x, tester.v4.z); Vector2 i0, i1; bool intersection = MathsHelper.LineTriIntersect(altV0, altV1, altV2, altV3, altV4, out i0, out i1); intersection |= MathsHelper.LineInTri(altV0, altV1, altV2, altV3, altV4); Handles.color = intersection ? Color.red : Color.green; Handles.DrawLine(tester.v0, tester.v1); Handles.DrawLine(tester.v2, tester.v3); Handles.DrawLine(tester.v4, tester.v3); Handles.DrawLine(tester.v4, tester.v2); }
public override void OnInspectorGUI() { Island island = (Island)target; island.IslandSourceMesh = EditorGUILayout.ObjectField(island.IslandSourceMesh, typeof(Mesh), true) as Mesh; island.SectionsX = EditorGUILayout.IntField("Slices X", island.SectionsX); island.SectionsY = EditorGUILayout.IntField("Slices Y", island.SectionsY); if (GUILayout.Button("Slice Mesh")) { if (island.IslandSourceMesh != null) { Mesh[,] meshes = MeshSlice.Slice(island.IslandSourceMesh, island.SectionsX, island.SectionsY, true, true); GameObject meshesObject = GameObjectHelper.FindChild(island.gameObject, "meshes", true); int i = 0; foreach (var mesh in meshes) { mesh.Optimize(); GameObject newObject = new GameObject("island_slice_" + i); newObject.transform.parent = meshesObject.transform; newObject.transform.localPosition = Vector3.zero; newObject.AddComponent <MeshRenderer>(); MeshFilter filter = newObject.AddComponent <MeshFilter>(); filter.mesh = mesh; i++; } } } if (GUILayout.Button("Reset")) { island.m_triangles.Clear(); MeshSlice.Triangle tri = new MeshSlice.Triangle(); tri.p0 = new Vector2(-1.0f, -1.0f); tri.p1 = new Vector2(1.0f, -1.0f); tri.p2 = new Vector2(0.0f, 1.0f); island.m_triangles.Add(tri); } if (GUILayout.Button("Slice")) { List <MeshSlice.Triangle> tris = island.m_triangles; List <MeshSlice.Triangle> outTris = new List <MeshSlice.Triangle>(); Vector2 v0, v1; foreach (var tri in tris) { if (MathsHelper.LineTriIntersect(island.sliceStart, island.sliceEnd, tri.p0, tri.p1, tri.p2, out v0, out v1)) { outTris.AddRange(MeshSlice.SliceTri(tri, island.sliceStart, island.sliceEnd)); } else { outTris.Add(tri); } } island.m_triangles = outTris; } }
public static Mesh[,] Slice(Mesh input, int sectionsX, int sectionsY, bool localUVs, bool showProgressBar) { Mesh[,] output = new Mesh[sectionsX, sectionsY]; // Mangle all the Mesh's triangle information into slice-friendly Triangle objects List <Triangle> triangles = new List <Triangle>(); if (showProgressBar) { EditorUtility.DisplayProgressBar("Slicing Mesh", "Generating Triangle Lists", 0.0f); } for (int i = 0; i < input.triangles.Length / 3; i++) { Triangle newTri = new Triangle(); newTri.y0 = input.vertices[input.triangles[i * 3]].y; newTri.y1 = input.vertices[input.triangles[i * 3 + 1]].y; newTri.y2 = input.vertices[input.triangles[i * 3 + 2]].y; newTri.p0 = new Vector2(input.vertices[input.triangles[i * 3]].x, input.vertices[input.triangles[i * 3]].z); newTri.p1 = new Vector2(input.vertices[input.triangles[i * 3 + 1]].x, input.vertices[input.triangles[i * 3 + 1]].z); newTri.p2 = new Vector2(input.vertices[input.triangles[i * 3 + 2]].x, input.vertices[input.triangles[i * 3 + 2]].z); newTri.uv0 = input.uv[input.triangles[i * 3]]; newTri.uv1 = input.uv[input.triangles[i * 3 + 1]]; newTri.uv2 = input.uv[input.triangles[i * 3 + 2]]; triangles.Add(newTri); } //Debug.Log("Located " + triangles.Count + " triangles"); // Ignoring Y for now. // Unused intersection points from intersection tests. Hear to appease the functions Vector2 inter0, inter1; float xDelta = input.bounds.size.x / (float)sectionsX; float yDelta = input.bounds.size.z / (float)sectionsY; for (int x = 1; x < sectionsX; x++) { List <Triangle> newTris = new List <Triangle>(); float sliceX = input.bounds.min.x + (x * xDelta); Vector2 sliceStart = new Vector2(sliceX, input.bounds.min.z - 1.0f); Vector2 sliceEnd = new Vector2(sliceX, input.bounds.max.z + 1.0f); foreach (var tri in triangles) { if (MathsHelper.LineTriIntersect(sliceStart, sliceEnd, tri.p0, tri.p1, tri.p2, out inter0, out inter1)) { //Debug.Log("Slicing... x"); newTris.AddRange(SliceTri(tri, sliceStart, sliceEnd)); } else { newTris.Add(tri); } } triangles = newTris; } for (int y = 1; y < sectionsY; y++) { List <Triangle> newTris = new List <Triangle>(); float sliceY = input.bounds.min.z + (y * yDelta); Vector2 sliceStart = new Vector2(input.bounds.min.x - 1.0f, sliceY); Vector2 sliceEnd = new Vector2(input.bounds.max.x + 1.0f, sliceY); foreach (var tri in triangles) { if (MathsHelper.LineTriIntersect(sliceStart, sliceEnd, tri.p0, tri.p1, tri.p2, out inter0, out inter1)) { //Debug.Log("Slicing... y"); newTris.AddRange(SliceTri(tri, sliceStart, sliceEnd)); } else { newTris.Add(tri); } } triangles = newTris; } EditorUtility.DisplayProgressBar("Slicing Mesh", "Allocating Sliced Triangles", 0.5f); //Debug.Log("Finished slicing with " + triangles.Count + " tris"); // Okay, so triangles *should* be full of slices triangles // Blast through each output mesh, gather owned triangles and fling them into the new mesh objects for (int i = 0; i < output.GetLength(0); i++) { for (int j = 0; j < output.GetLength(1); j++) { List <Triangle> candidateTris = new List <Triangle>(); float xMin = input.bounds.min.x + i * xDelta; float xMax = input.bounds.min.x + (i + 1) * xDelta; float yMin = input.bounds.min.z + j * yDelta; float yMax = input.bounds.min.z + (j + 1) * yDelta; List <Triangle> remainingTris = new List <Triangle>(); foreach (var tri in triangles) { // May have trouble with co-linear degenerates. *shakes fist* Vector2 averagePos = (tri.p0 + tri.p1 + tri.p2) / 3.0f; //Debug.Log("Average Pos: " + averagePos.x + ", " + averagePos.y); if (averagePos.x >= xMin && averagePos.x <= xMax && averagePos.y >= yMin && averagePos.y <= yMax) { candidateTris.Add(tri); } else { remainingTris.Add(tri); } } triangles = remainingTris; Debug.Log("Section " + i + " has " + candidateTris.Count + " tris"); output[i, j] = new Mesh(); Vector3[] verts = new Vector3[candidateTris.Count * 3]; int[] indices = new int[candidateTris.Count * 3]; Vector2[] uvs = new Vector2[candidateTris.Count * 3]; int count = 0; foreach (var tri in candidateTris) { verts[count] = new Vector3(tri.p0.x, tri.y0, tri.p0.y); verts[count + 1] = new Vector3(tri.p1.x, tri.y1, tri.p1.y); verts[count + 2] = new Vector3(tri.p2.x, tri.y2, tri.p2.y); indices[count] = count; bool thingy = MathsHelper.sign(tri.p0, tri.p1, tri.p2) <= 0.0f; if (thingy) { indices[count + 1] = count + 1; indices[count + 2] = count + 2; } else { indices[count + 1] = count + 2; indices[count + 2] = count + 1; } if (localUVs) { uvs[count].x = (verts[count].x - xMin) / (xMax - xMin); uvs[count].y = (verts[count].z - yMin) / (yMax - yMin); uvs[count + 1].x = (verts[count + 1].x - xMin) / (xMax - xMin); uvs[count + 1].y = (verts[count + 1].z - yMin) / (yMax - yMin); uvs[count + 2].x = (verts[count + 2].x - xMin) / (xMax - xMin); uvs[count + 2].y = (verts[count + 2].z - yMin) / (yMax - yMin); } else { uvs[count] = tri.uv0; uvs[count + 1] = tri.uv1; uvs[count + 2] = tri.uv2; } count += 3; } output[i, j].vertices = verts; output[i, j].triangles = indices; output[i, j].uv = uvs; } } EditorUtility.ClearProgressBar(); //Debug.LogError("Finished with " + triangles.Count + " triangles unassigned"); return(output); }
public static void GenerateLightmap(Building building, Room room, string textureOutputPath, int pixelSpread, bool filter) { #if UNITY_EDITOR List <IntersectionLine> m_intersections = new List <IntersectionLine>(); string roomID = building.BuildingName + "_" + room.Name + "_" + Building.s_floor_id; string wallsID = building.BuildingName + "_" + Building.s_walls_id; GameObject roomsObject = GameObjectHelper.FindChild(building.gameObject, Building.s_rooms_id, false); GameObject wallsObject = GameObjectHelper.FindChild(building.gameObject, wallsID, false); // TODO: Name this something else. Very confusing having roomObject and roomsObject GameObject roomObject = GameObjectHelper.FindChild(roomsObject, roomID, false); GameObject floorObject = GameObjectHelper.FindChild(roomObject, Building.s_floor_id, false); GameObject ambientObject = GameObjectHelper.FindChild(roomObject, Building.s_ambient_id, false); if (floorObject != null) { Debug.Log("Found: " + roomID); } else { Debug.Log("Couldn't find room: " + roomID); return; } if (wallsObject != null) { Debug.Log("Found: " + wallsID); } else { Debug.Log("Couldn't find walls: " + wallsID); return; } MeshFilter ambientFilter = ambientObject.GetComponent <MeshFilter>(); MeshFilter roomFilter = floorObject.GetComponent <MeshFilter>(); MeshFilter wallsFilter = wallsObject.GetComponent <MeshFilter>(); if (ambientFilter == null) { Debug.LogWarning("Ambient Filter missing for room: " + room.Name); return; } if (roomFilter == null) { Debug.LogWarning("Room Filter missing for room: " + room.Name); return; } if (wallsFilter == null) { Debug.LogWarning("Walls Filter missing for room: " + room.Name); return; } Mesh ambientMesh = ambientFilter.sharedMesh; Mesh roomMesh = roomFilter.sharedMesh; Mesh wallsMesh = wallsFilter.sharedMesh; if (ambientMesh == null) { Debug.LogWarning("Ambient Mesh missing for room: " + room.Name); return; } if (roomMesh == null) { Debug.LogWarning("Room Mesh missing for room: " + room.Name); return; } if (wallsMesh == null) { Debug.LogWarning("Walls Mesh missing for room: " + room.Name); return; } m_intersections.Clear(); int triangleCount = wallsMesh.triangles.Length / 3; for (int tri = 0; tri < triangleCount; ++tri) { IntersectionLine newLine0 = new IntersectionLine(); IntersectionLine newLine1 = new IntersectionLine(); IntersectionLine newLine2 = new IntersectionLine(); newLine0.start = wallsMesh.vertices[wallsMesh.triangles[tri * 3]]; newLine0.end = wallsMesh.vertices[wallsMesh.triangles[tri * 3 + 1]]; newLine1.start = wallsMesh.vertices[wallsMesh.triangles[tri * 3 + 1]]; newLine1.end = wallsMesh.vertices[wallsMesh.triangles[tri * 3 + 2]]; newLine2.start = wallsMesh.vertices[wallsMesh.triangles[tri * 3 + 2]]; newLine2.end = wallsMesh.vertices[wallsMesh.triangles[tri * 3]]; int triangleCountAlt = roomMesh.triangles.Length / 3; for (int triAlt = 0; triAlt < triangleCountAlt; ++triAlt) { IntersectionLine newLine0Alt = new IntersectionLine(); IntersectionLine newLine1Alt = new IntersectionLine(); IntersectionLine newLine2Alt = new IntersectionLine(); newLine0Alt.start = roomMesh.vertices[roomMesh.triangles[triAlt * 3]]; newLine0Alt.end = roomMesh.vertices[roomMesh.triangles[triAlt * 3 + 1]]; newLine1Alt.start = roomMesh.vertices[roomMesh.triangles[triAlt * 3 + 1]]; newLine1Alt.end = roomMesh.vertices[roomMesh.triangles[triAlt * 3 + 2]]; newLine2Alt.start = roomMesh.vertices[roomMesh.triangles[triAlt * 3 + 2]]; newLine2Alt.end = roomMesh.vertices[roomMesh.triangles[triAlt * 3]]; // BAH! Vector2 v0 = new Vector2(newLine0.start.x, newLine0.start.z); Vector2 v1 = new Vector2(newLine0.end.x, newLine0.end.z); Vector2 v2 = new Vector2(roomMesh.vertices[roomMesh.triangles[triAlt * 3]].x, roomMesh.vertices[roomMesh.triangles[triAlt * 3]].z); Vector2 v3 = new Vector2(roomMesh.vertices[roomMesh.triangles[triAlt * 3 + 1]].x, roomMesh.vertices[roomMesh.triangles[triAlt * 3 + 1]].z); Vector2 v4 = new Vector2(roomMesh.vertices[roomMesh.triangles[triAlt * 3 + 2]].x, roomMesh.vertices[roomMesh.triangles[triAlt * 3 + 2]].z); Vector2 intersection0, intersection1; bool intersect = MathsHelper.LineTriIntersect(v0, v1, v2, v3, v4, out intersection0, out intersection1); intersect |= MathsHelper.LineInTri(v0, v1, v2, v3, v4); if (intersect) { m_intersections.Add(newLine0); } v0 = new Vector2(newLine1.start.x, newLine1.start.z); v1 = new Vector2(newLine1.end.x, newLine1.end.z); intersect = MathsHelper.LineTriIntersect(v0, v1, v2, v3, v4, out intersection0, out intersection1); intersect |= MathsHelper.LineInTri(v0, v1, v2, v3, v4); if (intersect) { m_intersections.Add(newLine1); } v0 = new Vector2(newLine2.start.x, newLine2.start.z); v1 = new Vector2(newLine2.end.x, newLine2.end.z); intersect = MathsHelper.LineTriIntersect(v0, v1, v2, v3, v4, out intersection0, out intersection1); intersect |= MathsHelper.LineInTri(v0, v1, v2, v3, v4); if (intersect) { m_intersections.Add(newLine2); } } } // Create a texture, innit int mipLevel = 0; const int texWidth = 256; const int texHeight = 256; int mipWidth = texWidth >> mipLevel; int mipHeight = texHeight >> mipLevel; Debug.Log("Mip: " + mipWidth + ", " + mipHeight); Texture2D testTexture = new Texture2D(mipWidth, mipHeight); for (int x = 0; x < mipWidth; ++x) { for (int y = 0; y < mipHeight; ++y) { testTexture.SetPixel(x, y, new Color(1.0f, 1.0f, 1.0f, 1.0f)); } } foreach (var intersection in m_intersections) { Vector3 localStart = intersection.start - ambientMesh.bounds.min; Vector3 localEnd = intersection.end - ambientMesh.bounds.min; // trundle along the line and draw some things float delta = 1.0f / 1000.0f; for (int i = 0; i < 1000; i++) { for (int spreadX = -(pixelSpread / 2); spreadX < pixelSpread / 2; spreadX++) { for (int spreadY = -(pixelSpread / 2); spreadY < pixelSpread / 2; spreadY++) { Vector3 currentPixel = (localStart + (delta * i) * (localEnd - localStart)); currentPixel.x = currentPixel.x / ambientMesh.bounds.size.x; currentPixel.z = currentPixel.z / ambientMesh.bounds.size.z; currentPixel.x *= mipWidth; currentPixel.z *= mipHeight; currentPixel.x += spreadX; currentPixel.z += spreadY; //currentPixel.x = (float)mipWidth - currentPixel.x; //currentPixel.z = (float)mipHeight -currentPixel.z; if (currentPixel.x > 0.0f && currentPixel.z > 0.0f && currentPixel.x < mipWidth && currentPixel.z < mipHeight) { testTexture.SetPixel((int)currentPixel.x, (int)currentPixel.z, Color.black); } } } } } testTexture.EncodeToPNG(); string directory = System.IO.Path.GetDirectoryName(textureOutputPath); if (!Directory.Exists(directory)) { Directory.CreateDirectory(directory); } System.IO.File.WriteAllBytes(textureOutputPath, testTexture.EncodeToPNG()); string relative = textureOutputPath.Remove(textureOutputPath.IndexOf(Application.dataPath), Application.dataPath.Length); AssetDatabase.ImportAsset(relative, ImportAssetOptions.ForceSynchronousImport); #endif }