SingleAnimation LoadAnimation(string name, FileHandler Files) { if (Files.Exists("animations/" + name + ".anim")) { SingleAnimation created = new SingleAnimation(); created.Name = name; string[] data = Files.ReadText("animations/" + name + ".anim").SplitFast('\n'); int entr = 0; for (int i = 0; i < data.Length; i++) { if (data[i].StartsWith("//")) { continue; } string type = data[i]; if (data.Length <= i + 1 || data[i + 1] != "{") { break; } List <KeyValuePair <string, string> > entries = new List <KeyValuePair <string, string> >(); for (i += 2; i < data.Length; i++) { if (data[i].Trim().StartsWith("//")) { continue; } if (data[i] == "}") { break; } string[] dat = data[i].SplitFast(':'); if (dat.Length <= 1) { SysConsole.Output(OutputType.WARNING, "Invalid key dat: " + dat[0]); } else { string key = dat[0].Trim(); string value = dat[1].Substring(0, dat[1].Length - 1).Trim(); entries.Add(new KeyValuePair <string, string>(key, value)); } } bool isgeneral = type == "general" && entr == 0; SingleAnimationNode node = null; if (!isgeneral) { node = new SingleAnimationNode(); node.Name = type.ToLowerFast(); } foreach (KeyValuePair <string, string> entry in entries) { if (isgeneral) { if (entry.Key == "length") { created.Length = Utilities.StringToDouble(entry.Value); } else { SysConsole.Output(OutputType.WARNING, "Unknown GENERAL key: " + entry.Key); } } else { if (entry.Key == "positions") { string[] poses = entry.Value.SplitFast(' '); for (int x = 0; x < poses.Length; x++) { if (poses[x].Length > 0) { string[] posdata = poses[x].SplitFast('='); node.PosTimes.Add(Utilities.StringToDouble(posdata[0])); node.Positions.Add(new Location(Utilities.StringToFloat(posdata[1]), Utilities.StringToFloat(posdata[2]), Utilities.StringToFloat(posdata[3]))); } } } else if (entry.Key == "rotations") { string[] rots = entry.Value.SplitFast(' '); for (int x = 0; x < rots.Length; x++) { if (rots[x].Length > 0) { string[] posdata = rots[x].SplitFast('='); node.RotTimes.Add(Utilities.StringToDouble(posdata[0])); node.Rotations.Add(new Quaternion(Utilities.StringToFloat(posdata[1]), Utilities.StringToFloat(posdata[2]), Utilities.StringToFloat(posdata[3]), Utilities.StringToFloat(posdata[4]))); } } } else if (entry.Key == "parent") { node.ParentName = entry.Value.ToLowerFast(); } else if (entry.Key == "offset") { string[] posdata = entry.Value.SplitFast('='); node.Offset = new Location(Utilities.StringToFloat(posdata[0]), Utilities.StringToFloat(posdata[1]), Utilities.StringToFloat(posdata[2])); } else { SysConsole.Output(OutputType.WARNING, "Unknown NODE key: " + entry.Key); } } } if (!isgeneral) { created.Nodes.Add(node); created.node_map.Add(node.Name, node); } entr++; } foreach (SingleAnimationNode node in created.Nodes) { for (int i = 0; i < created.Nodes.Count; i++) { if (created.Nodes[i].Name == node.ParentName) { node.Parent = created.Nodes[i]; break; } } } created.Engine = this; return(created); } else { throw new Exception("Invalid animation file - file not found: animations/" + name + ".anim"); } }
/// <summary> /// Loads a model from .VMD (Voxalia Model Data) input. /// </summary> public Model3D LoadModel(byte[] data) { if (data.Length < 3 || data[0] != 'V' || data[1] != 'M' || data[2] != 'D') { throw new Exception("Model3D: Invalid header bits."); } byte[] dat_filt = new byte[data.Length - "VMD001".Length]; Array.ConstrainedCopy(data, "VMD001".Length, dat_filt, 0, dat_filt.Length); dat_filt = FileHandler.UnGZip(dat_filt); DataStream ds = new DataStream(dat_filt); DataReader dr = new DataReader(ds); Model3D mod = new Model3D(); Matrix matA = ReadMat(dr); mod.MatrixA = matA; int meshCount = dr.ReadInt(); mod.Meshes = new List <Model3DMesh>(meshCount); for (int m = 0; m < meshCount; m++) { Model3DMesh mesh = new Model3DMesh(); mod.Meshes.Add(mesh); mesh.Name = dr.ReadFullString(); int vertexCount = dr.ReadInt(); mesh.Vertices = new List <Vector3>(vertexCount); for (int v = 0; v < vertexCount; v++) { double f1 = dr.ReadFloat(); double f2 = dr.ReadFloat(); double f3 = dr.ReadFloat(); mesh.Vertices.Add(new Vector3(f1, f2, f3)); } int indiceCount = dr.ReadInt() * 3; mesh.Indices = new List <int>(indiceCount); for (int i = 0; i < indiceCount; i++) { mesh.Indices.Add(dr.ReadInt()); } int tcCount = dr.ReadInt(); mesh.TexCoords = new List <Vector2>(tcCount); for (int t = 0; t < tcCount; t++) { double f1 = dr.ReadFloat(); double f2 = dr.ReadFloat(); mesh.TexCoords.Add(new Vector2(f1, f2)); } int normCount = dr.ReadInt(); mesh.Normals = new List <Vector3>(normCount); for (int n = 0; n < normCount; n++) { double f1 = dr.ReadFloat(); double f2 = dr.ReadFloat(); double f3 = dr.ReadFloat(); mesh.Normals.Add(new Vector3(f1, f2, f3)); } int boneCount = dr.ReadInt(); mesh.Bones = new List <Model3DBone>(boneCount); for (int b = 0; b < boneCount; b++) { Model3DBone bone = new Model3DBone(); mesh.Bones.Add(bone); bone.Name = dr.ReadFullString(); int weights = dr.ReadInt(); bone.IDs = new List <int>(weights); bone.Weights = new List <double>(weights); for (int w = 0; w < weights; w++) { bone.IDs.Add(dr.ReadInt()); bone.Weights.Add(dr.ReadFloat()); } bone.MatrixA = ReadMat(dr); } } mod.RootNode = ReadSingleNode(null, dr); return(mod); }
public static void Populate(FileHandler files) { List <string> fileList = files.ListFiles("info/blocks/"); List <MaterialInfo> allmats = new List <MaterialInfo>((int)Material.NUM_DEFAULT); foreach (string file in fileList) { string f = file.ToLowerFast().After("/blocks/").Before(".blk"); Material mat; if (TryGetFromNameOrNumber(allmats, f, out mat)) { continue; } mat = (Material)Enum.Parse(typeof(Material), f.ToUpperInvariant()); string data = files.ReadText("info/blocks/" + f + ".blk"); string[] split = data.Replace("\r", "").Split('\n'); MaterialInfo inf = new MaterialInfo((int)mat); for (int i = 0; i < split.Length; i++) { if (split[i].StartsWith("//") || !split[i].Contains("=")) { continue; } string[] opt = split[i].SplitFast('=', 1); switch (opt[0].ToLowerFast()) { case "name": inf.SetName(opt[1]); break; case "plant": inf.Plant = opt[1]; break; case "sound": inf.Sound = (MaterialSound)Enum.Parse(typeof(MaterialSound), opt[1].ToUpperInvariant()); break; case "solidity": inf.Solidity = (MaterialSolidity)Enum.Parse(typeof(MaterialSolidity), opt[1].ToUpperInvariant()); break; case "speedmod": inf.SpeedMod = double.Parse(opt[1]); break; case "frictionmod": inf.FrictionMod = double.Parse(opt[1]); break; case "lightdamage": inf.LightDamage = double.Parse(opt[1]); break; case "lightemitrange": inf.LightEmitRange = double.Parse(opt[1]); break; case "lightemit": inf.LightEmit = Location.FromString(opt[1]); break; case "fogalpha": inf.FogAlpha = double.Parse(opt[1]); break; case "opaque": inf.Opaque = opt[1].ToLowerFast() == "true"; break; case "spreads": inf.Spreads = opt[1].ToLowerFast() == "true"; break; case "rendersatall": inf.RendersAtAll = opt[1].ToLowerFast() == "true"; break; case "breaksfromothertools": inf.BreaksFromOtherTools = opt[1].ToLowerFast() == "true"; break; case "fogcolor": inf.FogColor = Location.FromString(opt[1]); break; case "canrenderagainstself": inf.CanRenderAgainstSelf = opt[1].ToLowerFast() == "true"; break; case "spawntype": inf.SpawnType = (MaterialSpawnType)Enum.Parse(typeof(MaterialSpawnType), opt[1].ToUpperInvariant()); break; case "hardness": inf.Hardness = double.Parse(opt[1]); break; case "breaktime": inf.BreakTime = opt[1].ToLowerFast() == "infinity" ? double.PositiveInfinity : double.Parse(opt[1]); break; case "breaker": inf.Breaker = (MaterialBreaker)Enum.Parse(typeof(MaterialBreaker), opt[1].ToUpperInvariant()); break; case "breaksinto": inf.BreaksInto = (Material)Enum.Parse(typeof(Material), opt[1].ToUpperInvariant()); break; case "solidifiesinto": inf.SolidifiesInto = (Material)Enum.Parse(typeof(Material), opt[1].ToUpperInvariant()); break; case "bigspreadsas": inf.BigSpreadsAs = (Material)Enum.Parse(typeof(Material), opt[1].ToUpperInvariant()); break; case "texturebasic": for (int t = 0; t < (int)MaterialSide.COUNT; t++) { if (inf.Texture[t] == null) { inf.Texture[t] = opt[1].ToLowerFast(); } } break; case "texture_top": inf.Texture[(int)MaterialSide.TOP] = opt[1].ToLowerFast(); break; case "texture_bottom": inf.Texture[(int)MaterialSide.BOTTOM] = opt[1].ToLowerFast(); break; case "texture_xp": inf.Texture[(int)MaterialSide.XP] = opt[1].ToLowerFast(); break; case "texture_xm": inf.Texture[(int)MaterialSide.XM] = opt[1].ToLowerFast(); break; case "texture_yp": inf.Texture[(int)MaterialSide.YP] = opt[1].ToLowerFast(); break; case "texture_ym": inf.Texture[(int)MaterialSide.YM] = opt[1].ToLowerFast(); break; default: SysConsole.Output(OutputType.WARNING, "Invalid material option: " + opt[0]); break; } } while (allmats.Count <= (int)mat) { allmats.Add(null); } allmats[(int)mat] = inf; } int c = 0; Dictionary <string, int> TexturesToIDs = new Dictionary <string, int>(); for (int i = 0; i < allmats.Count; i++) { for (int t = 0; t < (int)MaterialSide.COUNT; t++) { string tex = allmats[i].Texture[t]; int res; if (TexturesToIDs.ContainsKey(tex)) { res = TexturesToIDs[tex]; } else { TexturesToIDs[tex] = c; res = c; c++; } allmats[i].TID[t] = res; } } Textures = new string[c]; foreach (KeyValuePair <string, int> val in TexturesToIDs) { Textures[val.Value] = val.Key; } lock (ALL_MATS) { SysConsole.Output(OutputType.INIT, "Loaded: " + allmats.Count + " materials!"); ALL_MATS = allmats; } }