Пример #1
0
            // Build voxel object
            public virtual float Build(Storage voxels, Bounds bounds)
            {
                // Check for given array
                if (voxels != null)
                {
                    if (!building)
                    {
                        int existingIndex;
                        int x, y, z;

                        // Get iterator
                        if (iterator == null)
                        {
                            iterator        = voxels.GetIterator();
                            currentIndex    = 0;
                            currentProgress = 0;
                        }

                        if (colorAssignments == null)
                        {
                            // Create empty list to color assignments to
                            colorAssignments = new Dictionary <Color, int>();
                        }
                        else
                        {
                            // Get current color index from existing hash map
                            currentIndex = colorAssignments.Count;
                        }

                        // Process voxels in steps
                        for (int number = 0; number < 256; ++number)
                        {
                            // Retrieve color and coordinate for current cell
                            Color color = iterator.GetNextColor(out x, out y, out z);

                            // Check for valid voxel
                            if (color.a > 0)
                            {
                                // Add assignment between color and vertex index, if it is not already included
                                if (!colorAssignments.TryGetValue(color, out existingIndex))
                                {
                                    colorAssignments.Add(color, currentIndex++);
                                }
                            }
                            else
                            {
                                iterator = null;
                                break;
                            }
                        }

                        // Return current progress when building has not been finished
                        if (iterator != null)
                        {
                            return(currentProgress = (float)iterator.Number / (float)(voxels.Count + 1) * 0.5f);
                        }
                        else
                        {
                            building = true;
                            texture  = null;
                        }
                    }

                    if (colorAssignments != null)
                    {
                        CoordinateAssignment assignment;
                        int column = 0, line = 0;

                        // Compute resolution to fit all voxels into a 2D surface
                        int textureWidth  = (int)Math.Pow(2, Math.Ceiling(Math.Log(Math.Sqrt(colorAssignments.Count)) / Math.Log(2)));
                        int textureHeight = (int)Math.Ceiling((double)colorAssignments.Count / (double)textureWidth);

                        // Make height 2^n, too, if flag is set
                        if (powerOfTwo)
                        {
                            textureHeight = (int)Math.Pow(2, Math.Ceiling(Math.Log((float)textureHeight) / Math.Log(2)));
                        }

                        //// Change resolution, if current does not match the required resolution
                        //if (texture != null && ((texture.width != textureWidth) || (texture.height != textureHeight)))
                        //{
                        //    try
                        //    {
                        //        texture.Resize(textureWidth, textureHeight, TextureFormat.ARGB32, false);

                        //        // Fill texture and calculate texture coordinates
                        //        foreach (KeyValuePair<Color, int> currentPixel in colorAssignments)
                        //        {
                        //            texture.SetPixel(column = currentPixel.Value % texture.width, line = currentPixel.Value / texture.width, currentPixel.Key);
                        //        }

                        //        iterator = null;
                        //    }
                        //    catch (System.Exception)
                        //    {
                        //        texture = null;
                        //    }
                        //}

                        if (texture == null)
                        {
                            if (textureWidth != 0 && textureHeight != 0)
                            {
                                // Create new texture instance
                                texture = new UnityEngine.Texture2D(textureWidth, textureHeight, TextureFormat.ARGB32, false);
                                if (texture != null)
                                {
                                    texture.filterMode = FilterMode.Point;
                                    texture.wrapMode   = TextureWrapMode.Clamp;
                                }
                            }

                            iterator = null;
                        }

                        if (texture != null)
                        {
                            // Check for non-empty array
                            if (voxels.Count > 0)
                            {
                                // Get iterator
                                if (iterator == null)
                                {
                                    iterator        = voxels.GetIterator();
                                    currentIndex    = 0;
                                    currentProgress = 0;

                                    // Create array to store coordinates to
                                    coordinateAssignments = new CoordinateAssignment[voxels.Count];
                                }

                                // Process voxels in steps
                                for (int number = 0; number < texture.width; ++number)
                                {
                                    // Retrieve color and coordinate for current cell
                                    int   index = iterator.Number;
                                    Color color = iterator.GetNextColor(out assignment.source.x, out assignment.source.y, out assignment.source.z);

                                    // Check for valid voxel
                                    if (color.a > 0)
                                    {
                                        // Get index for current color
                                        if (colorAssignments.TryGetValue(color, out currentIndex))
                                        {
                                            // Store color as pixel
                                            texture.SetPixel(column = currentIndex % texture.width, line = currentIndex / texture.width, color);

                                            // Calculate coordinate for center of the current texel
                                            assignment.target.x = ((float)column + 0.5f) / (float)texture.width;
                                            assignment.target.y = ((float)line + 0.5f) / (float)texture.height;

                                            // Store assigned coordinates to array
                                            coordinateAssignments[index] = assignment;
                                        }
                                    }
                                    else
                                    {
                                        iterator = null;
                                        break;
                                    }
                                }

                                // Return current progress when building has not been finished
                                if (iterator != null)
                                {
                                    return(currentProgress = (float)iterator.Number / (float)(voxels.Count + 1) * 0.5f + 0.5f);
                                }

                                // Unset remaining texels
                                for (column = colorAssignments.Count % texture.width, line = colorAssignments.Count / texture.width; line < texture.height; ++line)
                                {
                                    for (; column < texture.width; ++column)
                                    {
                                        texture.SetPixel(column, line, Color.clear);
                                    }

                                    column = 0;
                                }
                            }
                        }
                    }
                }

                // Check for texture and color array
                if (texture != null)
                {
                    // Apply color changes on texture
                    texture.Apply();
                }

                // Reset current processing data
                currentIndex     = 0;
                iterator         = null;
                colorAssignments = null;
                building         = false;

                return(currentProgress = 1);
            }
Пример #2
0
            // Build voxel object
            public virtual float Build(Storage voxels, Bounds bounds)
            {
                // Check for given array
                if (voxels != null)
                {
                    //if (colorAssignments != null)
                    {
                        // Check for non-empty array
                        if (voxels.Count > 0)
                        {
                            // Get iterator
                            if (iterator == null)
                            {
                                iterator        = voxels.GetIterator();
                                currentProgress = 0;
                            }

                            if (texture == null)
                            {
                                if (superSamplingCount <= 0)
                                {
                                    superSamplingCount = 1;
                                }

                                // Calculate target resolution
                                int textureWidth  = (voxels.Width + superSamplingCount - 1) / superSamplingCount;
                                int textureHeight = (voxels.Height + superSamplingCount - 1) / superSamplingCount;
                                int textureDepth  = (voxels.Depth + superSamplingCount - 1) / superSamplingCount;

                                // Make resolution 2^n, if flag is set
                                if (powerOfTwo)
                                {
                                    textureWidth  = (int)Math.Pow(2, Math.Ceiling(Math.Log((float)textureWidth) / Math.Log(2)));
                                    textureHeight = (int)Math.Pow(2, Math.Ceiling(Math.Log((float)textureHeight) / Math.Log(2)));
                                    textureDepth  = (int)Math.Pow(2, Math.Ceiling(Math.Log((float)textureDepth) / Math.Log(2)));
                                }

                                if (textureWidth != 0 && textureHeight != 0 && textureDepth != 0)
                                {
                                    texels = new Color[textureWidth * textureHeight * textureDepth];
                                    counts = new float[textureWidth * textureHeight * textureDepth];

                                    hdr |= voxels.HasHDR();

                                    // Create new texture instance
                                    texture = new UnityEngine.Texture3D(textureWidth, textureHeight, textureDepth, hdr ? TextureFormat.RGBAHalf : TextureFormat.RGBA32, 4);
                                    if (texture != null)
                                    {
                                        //texture.filterMode = FilterMode.Point;
                                        texture.wrapMode = TextureWrapMode.Clamp;
                                    }
                                }
                            }

                            if (texture != null)
                            {
                                // Process voxels in steps
                                for (int number = 0; number < 10; ++number)
                                {
                                    // Retrieve color and coordinate for current cell
                                    int   x, y, z;
                                    Color color = iterator.GetNextColor(out x, out y, out z);

                                    // Check for valid voxel
                                    if (color.a > 0)
                                    {
                                        var index = x / superSamplingCount + (y / superSamplingCount + z / superSamplingCount * texture.height) * texture.width;

                                        // Store color to texels array
                                        texels[index] += color;
                                        ++counts[index];
                                    }
                                    else
                                    {
                                        iterator = null;
                                        break;
                                    }
                                }

                                // Return current progress when building has not been finished
                                if (iterator != null)
                                {
                                    return(currentProgress = (float)iterator.Number / (float)(voxels.Count + 1));
                                }
                                else
                                {
                                    // Calculate weight factor for every source cell
                                    var samplingFactor = 1f / (superSamplingCount * superSamplingCount * superSamplingCount);

                                    // Normalize colors and expand edges or blend with background
                                    for (int index = 0; index < texels.Length; ++index)
                                    {
                                        if (counts[index] > 0)
                                        {
                                            if (expandEdges)
                                            {
                                                texels[index].r /= counts[index];
                                                texels[index].g /= counts[index];
                                                texels[index].b /= counts[index];
                                                texels[index].a *= samplingFactor;
                                            }
                                            else
                                            {
                                                texels[index] /= counts[index];
                                                texels[index] += backgroundColor * (1 - texels[index].a);
                                            }
                                        }
                                        else
                                        {
                                            if (!expandEdges)
                                            {
                                                texels[index] = backgroundColor;
                                            }
                                        }
                                    }

                                    if (expandEdges)
                                    {
                                        bool repeat;

                                        do
                                        {
                                            repeat = false;

                                            // Process all cells
                                            for (int index = 0; index < texels.Length; ++index)
                                            {
                                                // Check if current cell is empty
                                                if (counts[index] == 0)
                                                {
                                                    var column = index % texture.width;
                                                    var row    = index / texture.width % texture.height;
                                                    var slice  = index / texture.width / texture.height;

                                                    var color = new Color(0, 0, 0, 0);
                                                    var count = 0f;

                                                    // Sum up all colors of direct neighbor cells
                                                    for (int offset = 0; offset < 6; ++offset)
                                                    {
                                                        // Get offset by current index
                                                        var offsetX = offset == 0 ? -1 : offset == 1 ? 1 : 0;
                                                        var offsetY = offset == 2 ? -1 : offset == 3 ? 1 : 0;
                                                        var offsetZ = offset == 4 ? -1 : offset == 5 ? 1 : 0;

                                                        var offsetColumn = column + offsetX;
                                                        if (offsetColumn >= 0 && offsetColumn < texture.width)
                                                        {
                                                            var offsetRow = row + offsetY;
                                                            if (offsetRow >= 0 && offsetRow < texture.height)
                                                            {
                                                                var offsetSlice = slice + offsetZ;
                                                                if (offsetSlice >= 0 && offsetSlice < texture.depth)
                                                                {
                                                                    var offsetIndex = offsetColumn + (offsetRow + offsetSlice * texture.height) * texture.width;

                                                                    // Check if neighbor includes an original color or one that has been set in a previous iteration
                                                                    if (counts[offsetIndex] > 0)
                                                                    {
                                                                        // Sum color components and increase quantity counter for later normalization
                                                                        color += texels[offsetIndex];
                                                                        ++count;
                                                                    }
                                                                }
                                                            }
                                                        }
                                                    }

                                                    if (count > 0)
                                                    {
                                                        // Normalize target color but set full transparency
                                                        texels[index].r = color.r / count;
                                                        texels[index].g = color.g / count;
                                                        texels[index].b = color.b / count;
                                                        texels[index].a = 0;

                                                        // Flag index as processed in this loop and enable next one
                                                        counts[index] = -count;
                                                        repeat        = true;
                                                    }
                                                }
                                            }

                                            // Unset processing flags for next iteration
                                            for (int index = 0; index < texels.Length; ++index)
                                            {
                                                if (counts[index] < 0)
                                                {
                                                    counts[index] = -counts[index];
                                                }
                                            }
                                        }while (repeat);
                                    }

                                    // Transfer all texel colors to the texture
                                    texture.SetPixels(texels);
                                }
                            }
                        }
                    }
                }

                // Check for texture and color array
                if (texture != null)
                {
                    // Apply color changes on texture
                    texture.Apply();
                }

                // Reset current processing data
                iterator = null;

                return(currentProgress = 1);
            }