Esempio n. 1
0
        public static PCache FromFile(string filename)
        {
            PCache data = new PCache();

            List <string> header;
            long          offset;

            using (var stream = File.OpenRead(filename))
            {
                GetHeader(stream, out offset, out header);
            }

            if (header == null || header[0] != "pcache")
            {
                throw new Exception("Invalid header : missing magic number");
            }

            Format format = (Format)int.MaxValue;

            data.elementCount = 0;
            data.properties   = new List <PropertyDesc>();

            foreach (string line in header)
            {
                var words = line.Split(' ');
                switch (words[0].ToLower())
                {
                case "comment":     //do nothing
                    break;

                case "format":
                    if (words.Length != 3)
                    {
                        throw new Exception("Invalid format description :" + line);
                    }
                    switch (words[1])
                    {
                    case "ascii": format = Format.Ascii; break;

                    case "binary": format = Format.Binary; break;

                    default: throw new Exception("Invalid Format :" + words[1]);
                    }
                    break;

                case "elements":
                    if (words.Length != 2)
                    {
                        throw new Exception("Invalid element description  :" + line);
                    }
                    if (!int.TryParse(words[1], out data.elementCount))
                    {
                        throw new Exception("Invalid element count :" + words[1]);
                    }
                    break;

                case "property":
                    if (words.Length != 3)
                    {
                        throw new Exception("Invalid property description :" + line);
                    }
                    string property  = words[2];
                    string component = GetComponentName(property);
                    int    idx       = GetComponentIndex(property);
                    string type      = words[1];
                    int    stride    = GetPropertySize(type);
                    if (stride == 0)
                    {
                        throw new Exception("Invalid Type for " + property + " property : " + type);
                    }

                    PropertyDesc prop = new PropertyDesc()
                    {
                        Name           = property,
                        Type           = type,
                        ComponentName  = component,
                        ComponentIndex = idx,
                        Stride         = stride
                    };
                    data.properties.Add(prop);
                    break;

                case "end_header":
                    if (words.Length != 1)
                    {
                        throw new Exception("Invalid end_header description :" + line);
                    }
                    break;
                }
            }

            data.buckets = new List <List <object> >();

            foreach (var property in data.properties)
            {
                data.buckets.Add(new List <object>(data.elementCount));
            }

            if (format == Format.Binary)
            {
                using (var binaryReader = new BinaryReader(File.OpenRead(filename)))
                {
                    binaryReader.BaseStream.Seek(offset, SeekOrigin.Begin);
                    for (int i = 0; i < data.elementCount; i++)
                    {
                        for (int j = 0; j < data.properties.Count; j++)
                        {
                            var prop = data.properties[j];
                            switch (prop.Type)
                            {
                            case "short": data.buckets[j].Add(binaryReader.ReadInt16()); break;

                            case "ushort": data.buckets[j].Add(binaryReader.ReadUInt16()); break;

                            case "int": data.buckets[j].Add(binaryReader.ReadInt32()); break;

                            case "uint": data.buckets[j].Add(binaryReader.ReadUInt32()); break;

                            case "char": data.buckets[j].Add(binaryReader.ReadSByte()); break;

                            case "uchar": data.buckets[j].Add(binaryReader.ReadByte()); break;

                            case "float": data.buckets[j].Add(binaryReader.ReadSingle()); break;

                            case "double": data.buckets[j].Add(binaryReader.ReadDouble()); break;
                            }
                        }
                    }
                }
            }
            else if (format == Format.Ascii)
            {
                string[] lines = null;
                using (var reader = new StreamReader(File.OpenRead(filename)))
                {
                    reader.BaseStream.Seek(offset, SeekOrigin.Begin);
                    lines = reader.ReadToEnd().Replace("\r", "").Split(new char[] { '\n' }, StringSplitOptions.RemoveEmptyEntries);
                }

                if (lines.Length != data.elementCount)
                {
                    throw new InvalidOperationException(string.Format("Bad item amount, {0} expected in header, found {1}", data.elementCount, lines.Length));
                }

                for (int i = 0; i < data.elementCount; i++)
                {
                    string   line     = lines[i];
                    string[] elements = line.Split(' ');

                    for (int j = 0; j < data.properties.Count; j++)
                    {
                        var prop = data.properties[j];
                        switch (prop.Type)
                        {
                        case "short": data.buckets[j].Add(short.Parse(elements[j], CultureInfo.InvariantCulture)); break;

                        case "ushort": data.buckets[j].Add(ushort.Parse(elements[j], CultureInfo.InvariantCulture)); break;

                        case "int": data.buckets[j].Add(int.Parse(elements[j], CultureInfo.InvariantCulture)); break;

                        case "uint": data.buckets[j].Add(uint.Parse(elements[j], CultureInfo.InvariantCulture)); break;

                        case "char": data.buckets[j].Add(sbyte.Parse(elements[j], CultureInfo.InvariantCulture)); break;

                        case "uchar": data.buckets[j].Add(byte.Parse(elements[j], CultureInfo.InvariantCulture)); break;

                        case "float": data.buckets[j].Add(float.Parse(elements[j], CultureInfo.InvariantCulture)); break;

                        case "double": data.buckets[j].Add(double.Parse(elements[j], CultureInfo.InvariantCulture)); break;
                        }
                    }
                }
            }
            return(data);
        }
        void OnGUI_Texture()
        {
            GUILayout.Label("Texture baking", EditorStyles.boldLabel);

            m_Texture = (Texture2D)EditorGUILayout.ObjectField("Texture", m_Texture, typeof(Texture2D), false);

            m_DecimationThresholdMode = (DecimationThresholdMode)EditorGUILayout.EnumPopup("Decimation Threshold", m_DecimationThresholdMode);
            if (m_DecimationThresholdMode != DecimationThresholdMode.None)
            {
                m_Threshold = EditorGUILayout.Slider("Threshold", m_Threshold, 0.0f, 1.0f);
            }

            m_RandomizePixels = EditorGUILayout.Toggle("Randomize Pixels Order", m_RandomizePixels);
            if (m_RandomizePixels)
            {
                m_SeedPixels = EditorGUILayout.IntField("Seed", m_SeedPixels);
            }
            m_ExportColors = EditorGUILayout.Toggle("Export Colors", m_ExportColors);

            m_OutputFormat = (PCache.Format)EditorGUILayout.EnumPopup("File Format", m_OutputFormat);

            if (m_Texture != null)
            {
                if (GUILayout.Button("Save to pCache file..."))
                {
                    string fileName = EditorUtility.SaveFilePanelInProject("pCacheFile", m_Texture.name, "pcache", "Save PCache");
                    if (fileName != null)
                    {
                        PCache file = new PCache();
                        file.AddVector3Property("position");
                        if (m_ExportColors)
                        {
                            file.AddColorProperty("color");
                        }

                        List <Vector3> positions = new List <Vector3>();
                        List <Vector4> colors    = null;

                        if (m_ExportColors)
                        {
                            colors = new List <Vector4>();
                        }

                        ComputeTextureData(positions, colors);
                        file.SetVector3Data("position", positions);
                        if (m_ExportColors)
                        {
                            file.SetColorData("color", colors);
                        }

                        file.SaveToFile(fileName, m_OutputFormat);
                    }
                }

                using (new GUILayout.VerticalScope(EditorStyles.helpBox))
                {
                    EditorGUILayout.LabelField("Texture Statistics", EditorStyles.boldLabel);
                    EditorGUI.indentLevel++;
                    EditorGUILayout.IntField("Width", m_Texture.width);
                    EditorGUILayout.IntField("Height", m_Texture.height);
                    EditorGUILayout.IntField("Pixels count", m_Texture.width * m_Texture.height);
                    EditorGUI.indentLevel--;
                }
            }
        }
        PCache ComputePCacheFromMesh()
        {
            var meshCache = ComputeDataCache(m_Mesh);

            Picker picker = null;

            if (m_Distribution == Distribution.Sequential)
            {
                if (m_MeshBakeMode == MeshBakeMode.Vertex)
                {
                    picker = new SequentialPickerVertex(meshCache);
                }
                else if (m_MeshBakeMode == MeshBakeMode.Triangle)
                {
                    picker = new SequentialPickerTriangle(meshCache);
                }
            }
            else if (m_Distribution == Distribution.Random)
            {
                if (m_MeshBakeMode == MeshBakeMode.Vertex)
                {
                    picker = new RandomPickerVertex(meshCache, m_SeedMesh);
                }
                else if (m_MeshBakeMode == MeshBakeMode.Triangle)
                {
                    picker = new RandomPickerTriangle(meshCache, m_SeedMesh);
                }
            }
            else if (m_Distribution == Distribution.RandomUniformArea)
            {
                picker = new RandomPickerUniformArea(meshCache, m_SeedMesh);
            }
            if (picker == null)
            {
                throw new InvalidOperationException("Unable to find picker");
            }

            var positions = new List <Vector3>();
            var normals   = m_ExportNormals ? new List <Vector3>() : null;
            var colors    = m_ExportColors ? new List <Vector4>() : null;
            var uvs       = m_ExportUV ? new List <Vector4>() : null;

            for (int i = 0; i < m_OutputPointCount; ++i)
            {
                if (i % 64 == 0)
                {
                    var cancel = EditorUtility.DisplayCancelableProgressBar("pCache bake tool", string.Format("Sampling data... {0}/{1}", i, m_OutputPointCount), (float)i / (float)m_OutputPointCount);
                    if (cancel)
                    {
                        return(null);
                    }
                }

                var vertex = picker.GetNext();
                positions.Add(vertex.position);
                if (m_ExportNormals)
                {
                    normals.Add(vertex.normal);
                }
                if (m_ExportColors)
                {
                    colors.Add(vertex.color);
                }
                if (m_ExportUV)
                {
                    uvs.Add(vertex.uvs.Any() ? vertex.uvs[0] : Vector4.zero);
                }
            }

            var file = new PCache();

            file.AddVector3Property("position");
            if (m_ExportNormals)
            {
                file.AddVector3Property("normal");
            }
            if (m_ExportColors)
            {
                file.AddColorProperty("color");
            }
            if (m_ExportUV)
            {
                file.AddVector4Property("uv");
            }

            EditorUtility.DisplayProgressBar("pCache bake tool", "Generating pCache...", 0.0f);
            file.SetVector3Data("position", positions);
            if (m_ExportNormals)
            {
                file.SetVector3Data("normal", normals);
            }
            if (m_ExportColors)
            {
                file.SetColorData("color", colors);
            }
            if (m_ExportUV)
            {
                file.SetVector4Data("uv", uvs);
            }

            EditorUtility.ClearProgressBar();
            return(file);
        }
Esempio n. 4
0
        public override void OnImportAsset(AssetImportContext ctx)
        {
            try
            {
                PCache pcache = PCache.FromFile(ctx.assetPath);

                PointCacheAsset cache = ScriptableObject.CreateInstance <PointCacheAsset>();
                cache.name = "PointCache";
                ctx.AddObjectToAsset("PointCache", cache);
                ctx.SetMainObject(cache);

                List <InProperty> inProperties = new List <InProperty>();
                Dictionary <string, OutProperty>    outProperties = new Dictionary <string, OutProperty>();
                Dictionary <OutProperty, Texture2D> surfaces      = new Dictionary <OutProperty, Texture2D>();

                foreach (var prop in pcache.properties)
                {
                    OutProperty p_out;
                    if (outProperties.ContainsKey(prop.ComponentName))
                    {
                        p_out      = outProperties[prop.ComponentName];
                        p_out.Size = Math.Max(p_out.Size, prop.ComponentIndex + 1);
                    }
                    else
                    {
                        p_out = new OutProperty(prop.Type, prop.ComponentName, prop.ComponentIndex + 1);
                        outProperties.Add(prop.ComponentName, p_out);
                    }

                    inProperties.Add(new InProperty(prop.Type, prop.Name, prop.ComponentIndex, p_out));
                }


                int width, height;
                FindBestSize(pcache.elementCount, out width, out height);

                // Output Surface Creation
                foreach (var kvp in outProperties)
                {
                    TextureFormat surfaceFormat = TextureFormat.Alpha8;
                    switch (kvp.Value.PropertyType)
                    {
                    case "byte":
                        if (kvp.Value.Size == 1)
                        {
                            surfaceFormat = TextureFormat.Alpha8;
                        }
                        else
                        {
                            surfaceFormat = TextureFormat.RGBA32;
                        }
                        break;

                    case "float":
                        if (kvp.Value.Size == 1)
                        {
                            surfaceFormat = TextureFormat.RHalf;
                        }
                        else
                        {
                            surfaceFormat = TextureFormat.RGBAHalf;
                        }
                        break;

                    default: throw new NotImplementedException("Types other than byte/float are not supported yet");
                    }

                    Texture2D surface = new Texture2D(width, height, surfaceFormat, false);
                    surface.name = kvp.Key;
                    surfaces.Add(kvp.Value, surface);
                }

                cache.PointCount = pcache.elementCount;
                cache.surfaces   = new Texture2D[surfaces.Count];

                Dictionary <OutProperty, Color> outValues = new Dictionary <OutProperty, Color>();
                foreach (var kvp in outProperties)
                {
                    outValues.Add(kvp.Value, new Color());
                }

                for (int i = 0; i < pcache.elementCount; i++)
                {
                    int idx = 0;
                    foreach (var prop in inProperties)
                    {
                        float val = 0.0f;
                        switch (prop.PropertyType)
                        {
                        case "byte":
                            val = Mathf.Clamp01(((int)pcache.buckets[idx][i]) / 256.0f);
                            break;

                        case "float":
                            val = ((float)pcache.buckets[idx][i]);
                            break;

                        default: throw new NotImplementedException("Types other than byte/float are not supported yet");
                        }

                        SetPropValue(prop.Index, outValues, prop.OutProperty, val);
                        idx++;
                    }
                    foreach (var kvp in outProperties)
                    {
                        surfaces[kvp.Value].SetPixel(i % width, i / width, outValues[kvp.Value]);
                    }
                }

                int k = 0;

                foreach (var kvp in surfaces)
                {
                    kvp.Value.Apply();
                    kvp.Value.hideFlags = HideFlags.HideInHierarchy;
                    ctx.AddObjectToAsset(kvp.Key.Name, kvp.Value);
                    cache.surfaces[k] = kvp.Value;
                    k++;
                }
            }
            catch (System.Exception e)
            {
                Debug.LogException(e);
            }
        }