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); } }
public static PCache FromFile(string filename) { PCache data = new PCache(); Stream s = File.OpenRead(filename); List <string> header; long offset; GetHeader(s, out offset, out header); if (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) { s.Close(); // End Header, goto binary mode s = File.OpenRead(filename); BinaryReader b = new BinaryReader(s); s.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(b.ReadInt16()); break; case "ushort": data.buckets[j].Add(b.ReadUInt16()); break; case "int": data.buckets[j].Add(b.ReadInt32()); break; case "uint": data.buckets[j].Add(b.ReadUInt32()); break; case "byte": data.buckets[j].Add(b.ReadChar()); break; case "float": data.buckets[j].Add(b.ReadSingle()); break; case "double": data.buckets[j].Add(b.ReadDouble()); break; } } } } else if (format == Format.Ascii) { s.Close(); // End Header, goto ascii mode s = File.OpenRead(filename); StreamReader reader = new StreamReader(s); s.Seek(offset, SeekOrigin.Begin); string[] 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 "byte": 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); }