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);
    }
示例#2
0
    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;
        }
    }
示例#3
0
    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
    }