[TestCase(16777215, 255, 255, 255, 255)] // 2^24 = 16,777,216
    public void ValuesEqualTest(int value, params int[] colorBytes)
    {
        // pass in as byte params to allow for the TestCase to be a constant expression
        // https://stackoverflow.com/questions/19479817/how-do-i-put-new-listint-1-in-an-nunit-testcase
        Color32 color     = new Color32((byte)colorBytes[0], (byte)colorBytes[1], (byte)colorBytes[2], (byte)colorBytes[3]);
        int     calcValue = ColorConversion.Color32ToInt(color);

        Assert.AreEqual(value, calcValue, "{0} was NOT equal to {1}", value, calcValue);

        var calcColor = ColorConversion.IntToColor32(value);

        Assert.AreEqual(color, calcColor, "{0} was NOT equal to {1}", color, calcColor);
    }
Esempio n. 2
0
    /// <summary>
    /// Gets all of the visible silhouettes by rendering out the scene into a render texture storing the edge IDs.
    /// </summary>
    private void GetVisibleSilhouettes()
    {
        Stopwatch stopwatch = new Stopwatch();

        stopwatch.Start();

        visibleSilhouettes.Clear();

        edgeCamera.Render();

        RenderTexture.active = edgeCamera.targetTexture;

        storageTexture.ReadPixels(textureRect, 0, 0, false);
        storageTexture.Apply();

        RenderTexture.active = null;

        pixelData = storageTexture.GetPixels32();
        foreach (var piece in pixelData)
        {
            if (piece.a != 0)
            {
                //Debug.LogFormat("Data = {0}", ColorConversion.Color32ToInt(piece));

                // get the color as an integer index into the edges.  perform a -1 since it was stored with a +1 to allow 0s to be ignored.
                int edgeIndex = ColorConversion.Color32ToInt(piece) - 1;
                if (!visibleSilhouettes.ContainsKey(edgeIndex))
                {
                    visibleSilhouettes.Add(edgeIndex, silhouettes[edgeIndex]);
                }
            }
        }

        stopwatch.Stop();
        Debug.LogFormat("{0}: Getting {1} visible silhouettes took {2}ms", name, visibleSilhouettes.Count, stopwatch.ElapsedMilliseconds);
        stopwatch.Reset();

        Debug.Log("Saving edges.png");
        stopwatch.Start();
        System.IO.File.WriteAllBytes("edges.png", storageTexture.EncodeToPNG());
        stopwatch.Stop();
        Debug.LogFormat("{0}: Saving edges.png took {1}ms", name, stopwatch.ElapsedMilliseconds);
    }
Esempio n. 3
0
    private void GetSegments()
    {
        Stopwatch stopwatch = new Stopwatch();

        stopwatch.Start();

        Texture2D softwareRasterization = new Texture2D(storageTexture.width, storageTexture.height);

        silhouetteSegments.Clear();

        Debug.LogFormat("{0}: edgeCamera.pixelWidth={1}, storageTexture.width={2}", name, edgeCamera.pixelWidth, storageTexture.width);

        foreach (var edgeKVP in visibleSilhouettes)
        {
            Edge edge      = edgeKVP.Value;
            int  edgeIndex = edgeKVP.Key;

            // convert from model space to world space
            var vertexA = transform.TransformPoint(vertexBuffer[edge.IndexA]);
            var vertexB = transform.TransformPoint(vertexBuffer[edge.IndexB]);

            // convert from world space to screen space
            // bottom-left is (0,0) and top-right is (pixelWidth, pixelHeight)
            vertexA = edgeCamera.WorldToScreenPoint(vertexA);
            vertexB = edgeCamera.WorldToScreenPoint(vertexB);

            // ensure that vertex A is the left-most vertex
            if (vertexA.x > vertexB.x)
            {
                var temp = vertexA;
                vertexA = vertexB;
                vertexB = temp;
            }

            // "scan-convert" along the line in the render texture color data to see which part of the edge is actually present (a segment)
            // save off any neighboring edges encountered
            Segment segment = new Segment();
            segment.EdgeIndex = edgeIndex;
            int  textureWidth   = storageTexture.width;
            bool segmentStarted = false;
            int  slope          = Mathf.RoundToInt((vertexB.y - vertexA.y) / (vertexB.x - vertexA.x));
            int  y    = Mathf.RoundToInt(vertexA.y);
            int  endX = Mathf.RoundToInt(vertexB.x);
            for (int x = Mathf.RoundToInt(vertexA.x); x <= endX; x++)
            {
                softwareRasterization.SetPixel(x, y, ColorConversion.IntToColor32(edgeIndex));

                // TODO: Add range checks
                // read pixel and surrounding pixels
                int center    = ColorConversion.Color32ToInt(pixelData[y * textureWidth + x]) - 1;
                int upLeft    = ColorConversion.Color32ToInt(pixelData[(y - 1) * textureWidth + x - 1]) - 1;
                int up        = ColorConversion.Color32ToInt(pixelData[(y - 1) * textureWidth + x]) - 1;
                int upRight   = ColorConversion.Color32ToInt(pixelData[(y - 1) * textureWidth + x + 1]) - 1;
                int left      = ColorConversion.Color32ToInt(pixelData[y * textureWidth + x - 1]) - 1;
                int right     = ColorConversion.Color32ToInt(pixelData[y * textureWidth + x + 1]) - 1;
                int downLeft  = ColorConversion.Color32ToInt(pixelData[(y + 1) * textureWidth + x - 1]) - 1;
                int down      = ColorConversion.Color32ToInt(pixelData[(y + 1) * textureWidth + x]) - 1;
                int downRight = ColorConversion.Color32ToInt(pixelData[(y + 1) * textureWidth + x + 1]) - 1;

                //if (upLeft != -1 || up != -1 || upRight != -1 ||
                //    left != -1 || center != -1 || right != -1 ||
                //    downLeft != -1 || down != -1 || downRight != -1)
                //{
                //    Debug.LogFormat("Found actual edge!");
                //}

                // store any neighboring edges we encounter along this edge
                if (upLeft > 0 && upLeft != edgeIndex && !segment.NeighborEdges.Contains(upLeft))
                {
                    segment.NeighborEdges.Add(upLeft);
                }
                if (up > 0 && up != edgeIndex && !segment.NeighborEdges.Contains(up))
                {
                    segment.NeighborEdges.Add(up);
                }
                if (upRight > 0 && upRight != edgeIndex && !segment.NeighborEdges.Contains(upRight))
                {
                    segment.NeighborEdges.Add(upRight);
                }
                if (left > 0 && left != edgeIndex && !segment.NeighborEdges.Contains(left))
                {
                    segment.NeighborEdges.Add(left);
                }
                if (right > 0 && right != edgeIndex && !segment.NeighborEdges.Contains(right))
                {
                    segment.NeighborEdges.Add(right);
                }
                if (downLeft > 0 && downLeft != edgeIndex && !segment.NeighborEdges.Contains(downLeft))
                {
                    segment.NeighborEdges.Add(downLeft);
                }
                if (down > 0 && down != edgeIndex && !segment.NeighborEdges.Contains(down))
                {
                    segment.NeighborEdges.Add(upLeft);
                }
                if (downRight > 0 && downRight != edgeIndex && !segment.NeighborEdges.Contains(downRight))
                {
                    segment.NeighborEdges.Add(downRight);
                }

                // start or end the segment if the edge was detected or not
                if (upLeft == edgeIndex || up == edgeIndex || upRight == edgeIndex ||
                    left == edgeIndex || center == edgeIndex || right == edgeIndex ||
                    downLeft == edgeIndex || down == edgeIndex || downRight == edgeIndex)
                {
                    if (!segmentStarted)
                    {
                        segmentStarted    = true;
                        segment.EndpointA = new Vector3(x, y);
                    }
                }
                else
                {
                    if (segmentStarted)
                    {
                        // the segment is now ended
                        // TODO: Add support for multiple segments formed from the same edge
                        segment.EndpointB = new Vector3(x, y);
                        silhouetteSegments.Add(edgeIndex, segment);
                        break;
                    }
                }

                // increment y
                y = y + slope;
            }
        }

        System.IO.File.WriteAllBytes("softwareRasterization.png", softwareRasterization.EncodeToPNG());

        stopwatch.Stop();
        Debug.LogFormat("{0}: Getting {1} segments took {2}ms", name, silhouetteSegments.Count, stopwatch.ElapsedMilliseconds);
    }