// I'm completely totally serious public static NUD Create(VBN vbn) { Dictionary <string, string> files = new Dictionary <string, string>(); ZipArchive zip = ZipFile.OpenRead("lib\\Skapon.zip"); Random random = new Random(); int randomNumber = random.Next(0, 0xFFFFFF); NUT nut = new NUT(); foreach (ZipArchiveEntry e in zip.Entries) { byte[] b; using (BinaryReader br = new BinaryReader(e.Open())) { b = br.ReadBytes((int)e.Length); } var stream = new StreamReader(new MemoryStream(b)); string s = stream.ReadToEnd(); files.Add(e.Name, s); if (e.Name.EndsWith(".dds")) { NutTexture tex = new DDS(new FileData(b)).ToNutTexture(); nut.Nodes.Add(tex); tex.HashId = 0x40000000 + randomNumber; nut.glTexByHashId.Add(tex.HashId, NUT.CreateTexture2D(tex)); } } NUD nud = new NUD(); NUD.Mesh head = new NUD.Mesh(); nud.Nodes.Add(head); head.Text = "Skapon"; head.Nodes.Add(setToBone(scale(readPoly(files["head.obj"]), 1, 1, 1), vbn.bones[vbn.boneIndex("HeadN")], vbn)); head.Nodes.Add(setToBone(scale(readPoly(files["body.obj"]), 1, 1, 1), vbn.bones[vbn.boneIndex("BustN")], vbn)); head.Nodes.Add(setToBone(scale(readPoly(files["hand.obj"]), 1, 1, 1), vbn.bones[vbn.boneIndex("RHandN")], vbn)); head.Nodes.Add(setToBone(scale(readPoly(files["hand.obj"]), -1, -1, 1), vbn.bones[vbn.boneIndex("LHandN")], vbn)); head.Nodes.Add(setToBone(scale(readPoly(files["foot.obj"]), 1, 1, 1), vbn.bones[vbn.boneIndex("RFootJ")], vbn)); head.Nodes.Add(setToBone(scale(readPoly(files["foot.obj"]), -1, -1, -1), vbn.bones[vbn.boneIndex("LFootJ")], vbn)); foreach (NUD.Polygon p in head.Nodes) { p.materials[0].textures[0].hash = 0x40000000 + randomNumber; } nud.UpdateRenderMeshes(); return(nud); }
public static NUD.Polygon setToBone(NUD.Polygon poly, Bone b, VBN vbn) { foreach (NUD.Vertex v in poly.vertices) { v.boneIds.Clear(); v.boneIds.Add(vbn.bones.IndexOf(b)); Vector3 newpos = Vector3.TransformVector(Vector3.Zero, b.transform); v.pos += newpos; } return(poly); }
public void Apply(VBN bone) { for (int i = 0; i < nodes.Count; i++) { List <AnimType> used = new List <AnimType>(); Bone b = bone.bones[i]; Vector3 erot = ANIM.quattoeul(b.rot); foreach (DATAnimTrack track in nodes[i]) { KeyNode node = track.keys[0]; if (Debug) { Console.WriteLine("Bone " + i + " " + track.type + " " + node.value); } switch (track.type) { case AnimType.XPOS: b.pos.X = node.value; break; case AnimType.YPOS: b.pos.Y = node.value; break; case AnimType.ZPOS: b.pos.Z = node.value; break; case AnimType.XROT: erot.X = node.value; break; case AnimType.YROT: erot.Y = node.value; break; case AnimType.ZROT: erot.Z = node.value; break; } } b.rot = VBN.FromEulerAngles(erot.Z, erot.Y, erot.X); } bone.update(); }
public ModelContainer() { ImageKey = "folder"; SelectedImageKey = "folder"; nud = new NUD(); nut = new NUT(); vbn = new VBN(); mta = new MTA(); MOI = new MOI(); jtb = new JTB(); XMB = new XMBFile(); Checked = true; Refresh(); }
// temp stuff public static Dictionary <string, SkelAnimation> LoadAJ(string fname, VBN vbn) { // a note, I know that the main player file has the offsets for // animations, this is just for viewing FileData f = new FileData(fname); f.Endian = System.IO.Endianness.Big; int pos = 0; Dictionary <string, SkelAnimation> animations = new Dictionary <string, SkelAnimation>(); AnimationGroupNode group = new AnimationGroupNode() { Text = fname }; MainForm.Instance.animList.treeView1.Nodes.Add(group); while (pos < f.size()) { Console.WriteLine(pos.ToString("x")); int len = f.readInt(); DAT_Animation anim = new DAT_Animation(); anim.Read(new FileData(f.getSection(pos, len))); AnimTrack track = new AnimTrack(anim); if (pos == 0) { //track.Show(); } group.Nodes.Add(track.toAnimation(vbn)); SkelAnimation sa = track.BakeToSkel(vbn); //sa.Tag = track; //Runtime.Animations.Add(anim.Name, sa); // MainForm.Instance.animList.treeView1.Nodes.Add(anim.Name); animations.Add(anim.Name, sa); if (pos != 0) { track.Dispose(); track.Close(); } f.skip(len - 4); f.align(32); pos = f.pos(); } return(animations); }
public static Animation read(FileData d, VBN m) { d.Endian = Endianness.Big; d.seek(0x8); int versionNum = d.readInt(); d.seek(0x10); if (versionNum == 4) { return(readAnim(d, m)); } return(null); }
public void OpenSkeleton(string pathVBN, string pathJTB, string pathSB) { if (string.IsNullOrEmpty(pathVBN)) { return; } VBN = new VBN(pathVBN); if (!string.IsNullOrEmpty(pathJTB)) { JTB = new JTB(pathJTB); } if (!string.IsNullOrEmpty(pathSB)) { VBN.SwingBones.Read(pathSB); } }
public static void DrawVBN(VBN vbn) { if (vbn != null && Runtime.renderBones) { foreach (Bone bone in vbn.bones) { bone.Draw(); // if swing bones then draw swing radius /*if (vbn.swingBones.bones.Count > 0 && Runtime.renderSwag) * { * SB.SBEntry sb = null; * vbn.swingBones.TryGetEntry(bone.boneId, out sb); * if (sb != null) * { * // draw * if (bone.ParentBone != null) * { * int i = bone.parentIndex; * float degtorad = (float)(Math.PI / 180); * Vector3 pos_sb = Vector3.Transform(Vector3.Zero, * Matrix4.CreateTranslation(new Vector3(3, 3, 3)) * Matrix4.CreateScale(bone.sca) * Matrix4.CreateFromQuaternion(VBN.FromEulerAngles(sb.rx1 * degtorad, sb.ry1 * degtorad, sb.rz1 * degtorad)) * Matrix4.CreateTranslation(bone.pos) * vbn.bones[i].transform); * * Vector3 pos_sb2 = Vector3.Transform(Vector3.Zero, * Matrix4.CreateTranslation(new Vector3(3, 3, 3)) * Matrix4.CreateScale(bone.sca) * Matrix4.CreateFromQuaternion(VBN.FromEulerAngles(sb.rx2 * degtorad, sb.ry2 * degtorad, sb.rz2 * degtorad)) * Matrix4.CreateTranslation(bone.pos) * vbn.bones[i].transform); * * GL.Color3(Color.ForestGreen); * GL.Begin(PrimitiveType.LineLoop); * GL.Vertex3(pos_c); * GL.Vertex3(pos_sb); * GL.Vertex3(pos_sb2); * GL.End(); * } * } * }*/ } } }
public VBN getVBN() { VBN v = null; if (!vbnFileLabel.Text.Equals("")) { v = new VBN(vbnFileLabel.Text); } else { if (Runtime.ModelContainers.Count > 0) { v = Runtime.ModelContainers[0].vbn; } } return(v); }
private void listBox1_SelectedIndexChanged(object sender, EventArgs e) { dontChange = true; SB.SBEntry sbEntry = (SB.SBEntry)listBox1.SelectedItem; if (sbEntry == null) { return; } boneButton1.SetBone(VBN.GetBone(sbEntry.hash)); for (int i = 0; i < buttons.Length; i++) { Bone bone = VBN.GetBone(sbEntry.boneHashes[i]); buttons[i].SetBone(bone); } xMin.Value = (Decimal)sbEntry.rx1; xMax.Value = (Decimal)sbEntry.rx2; yMin.Value = (Decimal)sbEntry.ry1; yMax.Value = (Decimal)sbEntry.ry2; zMin.Value = (Decimal)sbEntry.rz1; zMax.Value = (Decimal)sbEntry.rz2; weightBox.Value = (Decimal)sbEntry.factor; numericUpDown1.Value = (Decimal)sbEntry.param1_1; numericUpDown2.Value = (Decimal)sbEntry.param1_2; numericUpDown3.Value = (Decimal)sbEntry.param1_3; numericUpDown4.Value = (Decimal)sbEntry.param2_1; numericUpDown5.Value = (Decimal)sbEntry.param2_2; numericUpDown6.Value = (Decimal)sbEntry.param2_3; numericUpDown7.Value = (Decimal)sbEntry.unks1[0]; numericUpDown8.Value = (Decimal)sbEntry.unks1[1]; numericUpDown9.Value = (Decimal)sbEntry.unks1[2]; numericUpDown10.Value = (Decimal)sbEntry.unks1[3]; numericUpDown11.Value = (Decimal)sbEntry.unks2[0]; numericUpDown12.Value = (Decimal)sbEntry.unks2[1]; numericUpDown13.Value = (Decimal)sbEntry.unks2[2]; numericUpDown14.Value = (Decimal)sbEntry.unks2[3]; numericUpDown15.Value = (Decimal)sbEntry.unks2[4]; numericUpDown16.Value = (Decimal)sbEntry.ints[0]; numericUpDown17.Value = (Decimal)sbEntry.ints[1]; numericUpDown18.Value = (Decimal)sbEntry.ints[2]; numericUpDown19.Value = (Decimal)sbEntry.ints[3]; dontChange = false; }
public void RenderHitboxAngles(Hitbox h, VBN vbn) { //Angle marker changes direction depending on conditions: //If hitbox is behind transN bone (as if the person being hit is located at the hitbox center) //If facing-restriction parameter of hitboxes is set to certain values (3 = forward, 4 = backward) float transN_Z = getBone(0, vbn).pos.Z; int facingRestr = h.FacingRestriction; int direction = 1; //check facing restriction values first, then check position if (facingRestr == 3) { direction = 1; } else if (facingRestr == 4) { direction = -1; } else if (h.va.Z < transN_Z) { direction = -1; } if (h.Angle <= 360) { GL.LineWidth(5f); GL.Begin(PrimitiveType.Lines); GL.Color4(Runtime.hitboxAnglesColor); GL.Vertex3(h.va); if (direction == 1) { GL.Vertex3(h.va + Vector3.Transform(new Vector3(0, 0, h.Size), Matrix3.CreateRotationX(-h.Angle * ((float)Math.PI / 180f)))); } else { GL.Vertex3(h.va + Vector3.Transform(new Vector3(0, 0, h.Size), Matrix3.CreateRotationX((180 + h.Angle) * ((float)Math.PI / 180f)))); } GL.End(); } //TODO: Add special angle marker for angles > 360 (and maybe a separate one for 361?) //An annular shape is recognizable but can slow down the gif encoder if it's too precise }
public bool essentialComparison(VBN compareTo) { // Because I don't want to override == just for a cursory bone comparison if (this.bones.Count != compareTo.bones.Count) { return(false); } for (int i = 0; i < this.bones.Count; i++) { if (this.bones[i].Name != compareTo.bones[i].Name) { return(false); } if (this.bones[i].pos != compareTo.bones[i].pos) { return(false); } } return(true); }
public float getBaseNodeValue(int nid, String type, VBN vbn) { //UNSAFE: Hacky fix if (nid == -1) { return(0); } switch (type) { case "X": return(vbn.bones[nid].position[0]); case "Y": return(vbn.bones[nid].position[1]); case "Z": return(vbn.bones[nid].position[2]); case "RX": return(vbn.bones[nid].rotation[0]); case "RY": return(vbn.bones[nid].rotation[1]); case "RZ": return(vbn.bones[nid].rotation[2]); case "SX": return(vbn.bones[nid].scale[0]); case "SY": return(vbn.bones[nid].scale[1]); case "SZ": return(vbn.bones[nid].scale[2]); } return(0); }
public static void Save(Animation anim, VBN Skeleton, String Fname) { using (System.IO.StreamWriter file = new System.IO.StreamWriter(@Fname)) { file.WriteLine("version 1"); file.WriteLine("nodes"); foreach (Bone b in Skeleton.bones) { file.WriteLine(Skeleton.bones.IndexOf(b) + " \"" + b.Text + "\" " + b.parentIndex); } file.WriteLine("end"); file.WriteLine("skeleton"); anim.SetFrame(0); for (int i = 0; i <= anim.FrameCount; i++) { anim.NextFrame(Skeleton); file.WriteLine("time " + i); foreach (Animation.KeyNode sb in anim.Bones) { Bone b = Skeleton.getBone(sb.Text); if (b == null) { continue; } Vector3 eul = ANIM.quattoeul(b.rot); file.WriteLine(Skeleton.bones.IndexOf(b) + " " + b.pos.X + " " + b.pos.Y + " " + b.pos.Z + " " + eul.X + " " + eul.Y + " " + eul.Z); } } file.WriteLine("end"); file.Close(); } }
public static void effectiveScale(NUD nud, VBN vbn, Matrix4 sca) { foreach (Bone b in vbn.bones) { Vector3 pos = Vector3.TransformVector(new Vector3(b.position[0], b.position[1], b.position[2]), sca); b.position[0] = pos.X; b.position[1] = pos.Y; b.position[2] = pos.Z; } vbn.reset(); foreach (NUD.Mesh mesh in nud.Nodes) { foreach (NUD.Polygon poly in mesh.Nodes) { foreach (NUD.Vertex v in poly.vertices) { v.pos = Vector3.TransformVector(v.pos, sca); } } } nud.UpdateRenderMeshes(); }
public void createANIM(string fname, VBN vbn) { using (System.IO.StreamWriter file = new System.IO.StreamWriter(@fname)) { file.WriteLine("animVersion 1.1;"); file.WriteLine("mayaVersion 2014 x64;\ntimeUnit ntscf;\nlinearUnit cm;\nangularUnit deg;\nstartTime 1;\nendTime " + (anim.frameCount + 1) + ";"); int i = 0; // writing node attributes foreach (Bone b in vbn.getBoneTreeOrder()) { i = vbn.boneIndex(b.Text); if (i < anim.nodes.Count) { // write the bone attributes // count the attributes List <DAT_Animation.DATAnimTrack> tracks = anim.nodes[i]; int tracknum = 0; if (tracks.Count == 0) { file.WriteLine("anim " + b.Text + " 0 0 0;"); } foreach (DAT_Animation.DATAnimTrack track in tracks) { switch (track.type) { case DAT_Animation.AnimType.XPOS: file.WriteLine("anim translate.translateX translateX " + b.Text + " 0 0 " + (tracknum++) + ";"); WriteAnimKey(file, i, track, false); break; case DAT_Animation.AnimType.YPOS: file.WriteLine("anim translate.translateY translateY " + b.Text + " 0 0 " + (tracknum++) + ";"); WriteAnimKey(file, i, track, false); break; case DAT_Animation.AnimType.ZPOS: file.WriteLine("anim translate.translateZ translateZ " + b.Text + " 0 0 " + (tracknum++) + ";"); WriteAnimKey(file, i, track, false); break; case DAT_Animation.AnimType.XROT: file.WriteLine("anim rotate.rotateX rotateX " + b.Text + " 0 0 " + (tracknum++) + ";"); WriteAnimKey(file, i, track, true); break; case DAT_Animation.AnimType.YROT: file.WriteLine("anim rotate.rotateY rotateY " + b.Text + " 0 0 " + (tracknum++) + ";"); WriteAnimKey(file, i, track, true); break; case DAT_Animation.AnimType.ZROT: file.WriteLine("anim rotate.rotateZ rotateZ " + b.Text + " 0 0 " + (tracknum++) + ";"); WriteAnimKey(file, i, track, true); break; case DAT_Animation.AnimType.XSCA: file.WriteLine("anim scale.scaleX scaleX " + b.Text + " 0 0 " + (tracknum++) + ";"); WriteAnimKey(file, i, track, false); break; case DAT_Animation.AnimType.YSCA: file.WriteLine("anim scale.scaleY scaleY " + b.Text + " 0 0 " + (tracknum++) + ";"); WriteAnimKey(file, i, track, false); break; case DAT_Animation.AnimType.ZSCA: file.WriteLine("anim scale.scaleZ scaleZ " + b.Text + " 0 0 " + (tracknum++) + ";"); WriteAnimKey(file, i, track, false); break; } } } else { file.WriteLine("anim " + b.Text + " 0 0 0;"); } } } }
public Bone(VBN v) { vbnParent = v; ImageKey = "bone"; SelectedImageKey = "bone"; }
public override string ToString() { return(VBN.BoneNameFromHash(hash)); }
public static void read(string fname, Animation a, VBN v) { StreamReader reader = File.OpenText(fname); string line; string current = ""; bool readBones = false; int frame = 0, prevframe = 0; KeyFrame k = new KeyFrame(); VBN vbn = v; if (v != null && v.bones.Count == 0) { readBones = true; } else { vbn = new VBN(); } while ((line = reader.ReadLine()) != null) { line = Regex.Replace(line, @"\s+", " "); string[] args = line.Replace(";", "").TrimStart().Split(' '); if (args[0].Equals("nodes") || args[0].Equals("skeleton") || args[0].Equals("end") || args[0].Equals("time")) { current = args[0]; if (args.Length > 1) { prevframe = frame; frame = int.Parse(args[1]); /*if (frame != prevframe + 1) { * Console.WriteLine ("Needs interpolation " + frame); * }*/ k = new KeyFrame(); k.frame = frame; //a.addKeyframe(k); } continue; } if (current.Equals("nodes")) { Bone b = new Bone(vbn); b.Text = args[1].Replace("\"", ""); b.parentIndex = int.Parse(args[2]); //b.children = new System.Collections.Generic.List<int> (); vbn.totalBoneCount++; vbn.bones.Add(b); Animation.KeyNode node = new Animation.KeyNode(b.Text); a.Bones.Add(node); } if (current.Equals("time")) { //Animation.KeyFrame n = new Animation.KeyFrame(); /*n.id = v.boneIndex(vbn.bones[int.Parse(args[0])].Text); * if (n.id == -1) * { * continue; * } * else * n.hash = v.bones[n.id].boneId;*/ // only if it finds the node //k.addNode(n); // reading the skeleton if this isn't an animation if (readBones && frame == 0) { Bone b = vbn.bones[int.Parse(args[0])]; b.position = new float[3]; b.rotation = new float[3]; b.scale = new float[3]; b.position[0] = float.Parse(args[1]); b.position[1] = float.Parse(args[2]); b.position[2] = float.Parse(args[3]); b.rotation[0] = float.Parse(args[4]); b.rotation[1] = float.Parse(args[5]); b.rotation[2] = float.Parse(args[6]); b.scale[0] = 1f; b.scale[1] = 1f; b.scale[2] = 1f; b.pos = new Vector3(float.Parse(args[1]), float.Parse(args[2]), float.Parse(args[3])); b.rot = VBN.FromEulerAngles(float.Parse(args[6]), float.Parse(args[5]), float.Parse(args[4])); if (b.parentIndex != -1) { vbn.bones [b.parentIndex].Nodes.Add(b); } } Animation.KeyNode bone = a.GetBone(vbn.bones[int.Parse(args[0])].Text); bone.RotType = Animation.RotationType.EULER; Animation.KeyFrame n = new Animation.KeyFrame(); n.Value = float.Parse(args[1]); n.Frame = frame; bone.XPOS.Keys.Add(n); n = new Animation.KeyFrame(); n.Value = float.Parse(args[2]); n.Frame = frame; bone.YPOS.Keys.Add(n); n = new Animation.KeyFrame(); n.Value = float.Parse(args[3]); n.Frame = frame; bone.ZPOS.Keys.Add(n); n = new Animation.KeyFrame(); n.Value = float.Parse(args[4]); n.Frame = frame; bone.XROT.Keys.Add(n); n = new Animation.KeyFrame(); n.Value = float.Parse(args[5]); n.Frame = frame; bone.YROT.Keys.Add(n); n = new Animation.KeyFrame(); n.Value = float.Parse(args[6]); n.Frame = frame; bone.ZROT.Keys.Add(n); if (args.Length > 7) { n = new Animation.KeyFrame(); n.Value = float.Parse(args[7]); n.Frame = frame; bone.XSCA.Keys.Add(n); n = new Animation.KeyFrame(); n.Value = float.Parse(args[8]); n.Frame = frame; bone.YSCA.Keys.Add(n); n = new Animation.KeyFrame(); n.Value = float.Parse(args[9]); n.Frame = frame; bone.ZSCA.Keys.Add(n); } } } a.FrameCount = frame; vbn.boneCountPerType[0] = (uint)vbn.bones.Count; vbn.update(); }
public static Bone getBone(int bone, VBN VBN) { Tuple <int, int> boneInfo = translateScriptBoneId(bone); int bid = boneInfo.Item1; int jtbIndex = boneInfo.Item2; Bone b = new Bone(null); if (bone != -1) { //foreach (ModelContainer m in ModelContainers) { // ModelContainers should store Hitbox data or have them linked since it will use last // modelcontainer bone for hitbox display (which might not be the character model). // This is especially important for the future when importing weapons for some moves. if (VBN != null) { try //Try used to avoid bone not found issue that crashes the application { if (VBN.JointTable.Tables.Count < 1) { b = VBN.bones[bid]; } else { if (jtbIndex == 0) { // Special rule for table 0, index 0 is *always* TransN, and index 1 counts as index 0 if (bid <= 0) { b = VBN.bones.Find(item => item.Name == "TransN"); if (b == null) { b = VBN.bones[0]; } } else // Index 2 counts as index 1, etc { b = VBN.bones[VBN.JointTable.Tables[jtbIndex][bid - 1]]; } } else if (jtbIndex < VBN.JointTable.Tables.Count) { // Extra joint tables don't have the TransN rule b = VBN.bones[VBN.JointTable.Tables[jtbIndex][bid]]; } else { //If there is no jointTable but bone is >1000 then don't look into a another joint table //This makes some weapons like Luma have hitboxes visualized //b = m.vbn.bones[bid]; b = VBN.bones[VBN.JointTable.Tables[VBN.JointTable.Tables.Count - 1][bid]]; } } } catch { } } } } return(b); }
public void nextFrame(VBN vbn) { if (frame >= frames.Count) { return; } if (frame == 0 && Main) { vbn.reset(); foreach (ModelContainer con in Runtime.ModelContainers) { if (con.nud != null && con.mta != null) { con.nud.applyMTA(con.mta, 0); } } } if (children.Count > 0) { Main = true; } foreach (object child in children) { if (child is SkelAnimation) { ((SkelAnimation)child).setFrame(frame); ((SkelAnimation)child).nextFrame(vbn); } if (child is MTA) { foreach (ModelContainer con in Runtime.ModelContainers) { if (con.nud != null) { con.nud.applyMTA(((MTA)child), frame); } } } } KeyFrame key = frames[frame]; foreach (KeyNode n in key.nodes) { //if (n.id == -1) // continue; //if (n.hash == 0) { //continue; //n.hash = vbn.bones [n.id].boneId; //} int id = -1; foreach (Bone bo in vbn.bones) { if (bo.boneId == n.hash) { id = vbn.bones.IndexOf(bo); n.id = id; break; } } if (id == -1) { continue; } Bone b = vbn.bones[id]; if (n.t_type != -1) { b.pos = n.t; } if (n.r_type != -1) { //if(new string(b.boneName).Equals("HeadN")) // Console.WriteLine(n.r.ToString() + (n.r.X + n.r.Y + n.r.X + n.r.W)); //Console.WriteLine(new string(b.boneName) + " " + b.rot.ToString() + " " + n.r.ToString() + "\n" + (n.r.X + n.r.Y + n.r.X + n.r.W)); b.rot = n.r; } if (n.s_type != -1) { b.sca = n.s; } else { b.sca = new Vector3(b.scale[0], b.scale[1], b.scale[2]); } } frame++; if (frame >= frames.Count) { frame = 0; } vbn.update(); }
public static Animation read(string filename, VBN vbn) { Animation a = new Animation(filename); Animation.KeyNode current = null; Animation.KeyFrame att = new Animation.KeyFrame(); StreamReader reader = File.OpenText(filename); string line; AnimHeader header = new AnimHeader(); bool inHeader = true; bool inKeys = false; string type = ""; while ((line = reader.ReadLine()) != null) { string[] args = line.Replace(";", "").TrimStart().Split(' '); if (inHeader) { if (args[0].Equals("anim")) { inHeader = false; } else if (args[0].Equals("animVersion")) { header.animVersion = args[1]; } else if (args[0].Equals("mayaVersion")) { header.mayaVersion = args[1]; } else if (args[0].Equals("startTime")) { header.startTime = float.Parse(args[1]); } else if (args[0].Equals("endTime")) { header.endTime = float.Parse(args[1]); } else if (args[0].Equals("startUnitless")) { header.startUnitless = float.Parse(args[1]); } else if (args[0].Equals("endUnitless")) { header.endUnitless = float.Parse(args[1]); } else if (args[0].Equals("timeUnit")) { header.timeUnit = args[1]; } else if (args[0].Equals("linearUnit")) { header.linearUnit = args[1]; } else if (args[0].Equals("angularUnit")) { header.angularUnit = args[1]; } } if (!inHeader) { if (inKeys) { if (args[0].Equals("}")) { inKeys = false; continue; } Animation.KeyFrame k = new Animation.KeyFrame(); //att.keys.Add (k); if (type.Contains("translate")) { if (type.Contains("X")) { current.XPOS.Keys.Add(k); } if (type.Contains("Y")) { current.YPOS.Keys.Add(k); } if (type.Contains("Z")) { current.ZPOS.Keys.Add(k); } } if (type.Contains("rotate")) { if (type.Contains("X")) { current.XROT.Keys.Add(k); } if (type.Contains("Y")) { current.YROT.Keys.Add(k); } if (type.Contains("Z")) { current.ZROT.Keys.Add(k); } } if (type.Contains("scale")) { if (type.Contains("X")) { current.XSCA.Keys.Add(k); } if (type.Contains("Y")) { current.YSCA.Keys.Add(k); } if (type.Contains("Z")) { current.ZSCA.Keys.Add(k); } } k.Frame = float.Parse(args [0]) - 1; k.Value = float.Parse(args [1]); if (type.Contains("rotate")) { k.Value *= (float)(Math.PI / 180f); } //k.intan = (args [2]); //k.outtan = (args [3]); if (args.Length > 7 && att.Weighted) { k.In = float.Parse(args[7]) * (float)(Math.PI / 180f); k.Out = float.Parse(args[8]) * (float)(Math.PI / 180f); } } if (args [0].Equals("anim")) { inKeys = false; if (args.Length == 5) { //TODO: finish this type // can be name of attribute } if (args.Length == 7) { // see of the bone of this attribute exists current = null; foreach (Animation.KeyNode b in a.Bones) { if (b.Text.Equals(args [3])) { current = b; break; } } if (current == null) { current = new Animation.KeyNode(args[3]); current.RotType = Animation.RotationType.EULER; a.Bones.Add(current); } current.Text = args [3]; att = new Animation.KeyFrame(); att.InterType = Animation.InterpolationType.HERMITE; type = args [2]; //current.Nodes.Add (att); // row child attribute aren't needed here } } /*if (args [0].Equals ("input")) * att.input = args [1]; * if (args [0].Equals ("output")) * att.output = args [1]; * if (args [0].Equals ("preInfinity")) * att.preInfinity = args [1]; * if (args [0].Equals ("postInfinity")) * att.postInfinity = args [1];*/ if (args[0].Equals("weighted")) { att.Weighted = args[1].Equals("1"); } // begining keys section if (args [0].Contains("keys")) { inKeys = true; } } } int startTime = (int)Math.Ceiling(header.startTime); int endTime = (int)Math.Ceiling(header.endTime); a.FrameCount = (endTime + 1) - startTime; reader.Close(); return(a); }
public static void CreateANIM(string fname, Animation a, VBN vbn) { using (System.IO.StreamWriter file = new System.IO.StreamWriter(@fname)) { AnimHeader header = new AnimHeader(); file.WriteLine("animVersion " + header.animVersion + ";"); file.WriteLine("mayaVersion " + header.mayaVersion + ";"); file.WriteLine("timeUnit " + header.timeUnit + ";"); file.WriteLine("linearUnit " + header.linearUnit + ";"); file.WriteLine("angularUnit " + header.angularUnit + ";"); file.WriteLine("startTime " + 1 + ";"); file.WriteLine("endTime " + a.FrameCount + ";"); a.SetFrame(a.FrameCount - 1); //from last frame for (int li = 0; li < a.FrameCount; ++li) //go through each frame with nextFrame { a.NextFrame(vbn); } a.NextFrame(vbn); //go on first frame int i = 0; // writing node attributes foreach (Bone b in vbn.getBoneTreeOrder()) { i = vbn.boneIndex(b.Text); if (a.HasBone(b.Text)) { // write the bone attributes // count the attributes Animation.KeyNode n = a.GetBone(b.Text); int ac = 0; if (n.XPOS.HasAnimation()) { file.WriteLine("anim translate.translateX translateX " + b.Text + " 0 0 " + (ac++) + ";"); writeKey(file, n.XPOS, n, a.Size(), "translateX"); file.WriteLine("}"); } if (n.YPOS.HasAnimation()) { file.WriteLine("anim translate.translateY translateY " + b.Text + " 0 0 " + (ac++) + ";"); writeKey(file, n.YPOS, n, a.Size(), "translateY"); file.WriteLine("}"); } if (n.ZPOS.HasAnimation()) { file.WriteLine("anim translate.translateZ translateZ " + b.Text + " 0 0 " + (ac++) + ";"); writeKey(file, n.ZPOS, n, a.Size(), "translateZ"); file.WriteLine("}"); } if (n.XROT.HasAnimation()) { file.WriteLine("anim rotate.rotateX rotateX " + b.Text + " 0 0 " + (ac++) + ";"); writeKey(file, n.XROT, n, a.Size(), "rotateX"); file.WriteLine("}"); } if (n.YROT.HasAnimation()) { file.WriteLine("anim rotate.rotateY rotateY " + b.Text + " 0 0 " + (ac++) + ";"); writeKey(file, n.YROT, n, a.Size(), "rotateY"); file.WriteLine("}"); } if (n.ZROT.HasAnimation()) { file.WriteLine("anim rotate.rotateZ rotateZ " + b.Text + " 0 0 " + (ac++) + ";"); writeKey(file, n.ZROT, n, a.Size(), "rotateZ"); file.WriteLine("}"); } if (n.XSCA.HasAnimation()) { file.WriteLine("anim scale.scaleX scaleX " + b.Text + " 0 0 " + (ac++) + ";"); writeKey(file, n.XSCA, n, a.Size(), "scaleX"); file.WriteLine("}"); } if (n.YSCA.HasAnimation()) { file.WriteLine("anim scale.scaleY scaleY " + b.Text + " 0 0 " + (ac++) + ";"); writeKey(file, n.YSCA, n, a.Size(), "scaleY"); file.WriteLine("}"); } if (n.ZSCA.HasAnimation()) { file.WriteLine("anim scale.scaleZ scaleZ " + b.Text + " 0 0 " + (ac++) + ";"); writeKey(file, n.ZSCA, n, a.Size(), "scaleZ"); file.WriteLine("}"); } } else { file.WriteLine("anim " + b.Text + " 0 0 0;"); } } } }
public FSKLTreePanel(VBN vbn) : this() { VBN = vbn; treeRefresh(); }
public static Bone getNodeId(VBN vbn, int node) { return(vbn.bones[node]); }
public void NextFrame(VBN skeleton, bool isChild = false) { if (Frame >= FrameCount) { return; } if (Frame == 0 && !isChild) { skeleton.reset(); } foreach (object child in Children) { if (child is Animation) { ((Animation)child).SetFrame(Frame); ((Animation)child).NextFrame(skeleton, isChild: true); } if (child is MTA) { //foreach (ModelContainer con in Runtime.ModelContainers) { if (((ModelContainer)skeleton.Parent).NUD != null) { ((ModelContainer)skeleton.Parent).NUD.ApplyMta(((MTA)child), (int)Frame); } } } if (child is BFRES.MTA) //For BFRES { { if (((ModelContainer)skeleton.Parent).BFRES != null) { ((ModelContainer)skeleton.Parent).BFRES.ApplyMta(((BFRES.MTA)child), (int)Frame); } } } } bool Updated = false; // no need to update skeleton of animations that didn't change foreach (KeyNode node in Bones) { // Get Skeleton Node Bone b = null; if (node.Hash == -1) { b = skeleton.getBone(node.Text); } else { b = skeleton.GetBone((uint)node.Hash); } if (b == null) { continue; } Updated = true; if (node.XPOS.HasAnimation() && b.boneType != 3) { b.pos.X = node.XPOS.GetValue(Frame); } if (node.YPOS.HasAnimation() && b.boneType != 3) { b.pos.Y = node.YPOS.GetValue(Frame); } if (node.ZPOS.HasAnimation() && b.boneType != 3) { b.pos.Z = node.ZPOS.GetValue(Frame); } if (node.XSCA.HasAnimation()) { b.sca.X = node.XSCA.GetValue(Frame); } else { b.sca.X = 1; } if (node.YSCA.HasAnimation()) { b.sca.Y = node.YSCA.GetValue(Frame); } else { b.sca.Y = 1; } if (node.ZSCA.HasAnimation()) { b.sca.Z = node.ZSCA.GetValue(Frame); } else { b.sca.Z = 1; } if (node.XROT.HasAnimation() || node.YROT.HasAnimation() || node.ZROT.HasAnimation()) { if (node.RotType == RotationType.QUATERNION) { KeyFrame[] x = node.XROT.GetFrame(Frame); KeyFrame[] y = node.YROT.GetFrame(Frame); KeyFrame[] z = node.ZROT.GetFrame(Frame); KeyFrame[] w = node.WROT.GetFrame(Frame); Quaternion q1 = new Quaternion(x[0].Value, y[0].Value, z[0].Value, w[0].Value); Quaternion q2 = new Quaternion(x[1].Value, y[1].Value, z[1].Value, w[1].Value); if (x[0].Frame == Frame) { b.rot = q1; } else if (x[1].Frame == Frame) { b.rot = q2; } else { b.rot = Quaternion.Slerp(q1, q2, (Frame - x[0].Frame) / (x[1].Frame - x[0].Frame)); } } else if (node.RotType == RotationType.EULER) { float x = node.XROT.HasAnimation() ? node.XROT.GetValue(Frame) : b.rotation[0]; float y = node.YROT.HasAnimation() ? node.YROT.GetValue(Frame) : b.rotation[1]; float z = node.ZROT.HasAnimation() ? node.ZROT.GetValue(Frame) : b.rotation[2]; b.rot = EulerToQuat(z, y, x); } } } Frame += 1f; if (Frame >= FrameCount) { Frame = 0; } if (!isChild && Updated) { skeleton.update(); } }
public static byte[] createOMO(SkelAnimation a, VBN vbn) { List <int> nodeid = a.getNodes(true, vbn); int startNode = 0; int sizeNode = nodeid.Count; FileOutput o = new FileOutput(); o.Endian = Endianness.Big; FileOutput t1 = new FileOutput(); t1.Endian = Endianness.Big; FileOutput t2 = new FileOutput(); t2.Endian = Endianness.Big; o.writeString("OMO "); o.writeShort(1); //idk o.writeShort(3); //idk o.writeInt(0x091E100C); //flags?? o.writeShort(0); //padding o.writeShort(sizeNode); // numOfNodes o.writeShort(a.frames.Count); // frame size o.writeShort(0); // frame start ?? o.writeInt(0); o.writeInt(0); o.writeInt(0); o.writeIntAt(o.size(), 0x14); // ASSESSMENT KeyNode[] minmax = new KeyNode[sizeNode]; bool[] hasScale = new bool[sizeNode]; bool[] hasTrans = new bool[sizeNode]; bool[] hasRot = new bool[sizeNode]; bool[] conScale = new bool[sizeNode]; bool[] conTrans = new bool[sizeNode]; bool[] conRot = new bool[sizeNode]; a.setFrame(0); for (int i = 0; i < a.size(); i++) { a.nextFrame(vbn); for (int j = 0; j < nodeid.Count; j++) { Bone node = getNodeId(vbn, nodeid[j]); if (minmax[j] == null) { hasRot[j] = false; hasScale[j] = false; hasTrans[j] = false; KeyNode n = a.getFirstNode(nodeid[j]); if (n != null) { if (n.r_type != -1) { hasRot[j] = true; } if (n.t_type != -1) { hasTrans[j] = true; } if (n.s_type != -1) { hasScale[j] = true; } } minmax[j] = new KeyNode(); minmax[j].t = new Vector3(999f, 999f, 999f); minmax[j].r = new Quaternion(999f, 999f, 999f, 999f); minmax[j].s = new Vector3(999f, 999f, 999f); minmax[j].t2 = new Vector3(-999f, -999f, -999f); minmax[j].r2 = new Quaternion(-999f, -999f, -999f, -999f); minmax[j].s2 = new Vector3(-999f, -999f, -999f); } if (node.pos.X < minmax[j].t.X) { minmax[j].t.X = node.pos.X; } if (node.pos.X > minmax[j].t2.X) { minmax[j].t2.X = node.pos.X; } if (node.pos.Y < minmax[j].t.Y) { minmax[j].t.Y = node.pos.Y; } if (node.pos.Y > minmax[j].t2.Y) { minmax[j].t2.Y = node.pos.Y; } if (node.pos.Z < minmax[j].t.Z) { minmax[j].t.Z = node.pos.Z; } if (node.pos.Z > minmax[j].t2.Z) { minmax[j].t2.Z = node.pos.Z; } // float[] fix = Node.fix360(node.nrx, node.nry, node.nrz); //float[] f = Bone.CalculateRotation(node.nrx, node.nry, node.nrz); Quaternion r = node.rot; if (r.X < minmax[j].r.X) { minmax[j].r.X = r.X; } if (r.X > minmax[j].r2.X) { minmax[j].r2.X = r.X; } if (r.Y < minmax[j].r.Y) { minmax[j].r.Y = r.Y; } if (r.Y > minmax[j].r2.Y) { minmax[j].r2.Y = r.Y; } if (r.Z < minmax[j].r.Z) { minmax[j].r.Z = r.Z; } if (r.Z > minmax[j].r2.Z) { minmax[j].r2.Z = r.Z; } if (node.sca.X < minmax[j].s.X) { minmax[j].s.X = node.sca.X; } if (node.sca.X > minmax[j].s2.X) { minmax[j].s2.X = node.sca.X; } if (node.sca.Y < minmax[j].s.Y) { minmax[j].s.Y = node.sca.Y; } if (node.sca.Y > minmax[j].s2.Y) { minmax[j].s2.Y = node.sca.Y; } if (node.sca.Z < minmax[j].s.Z) { minmax[j].s.Z = node.sca.Z; } if (node.sca.Z > minmax[j].s2.Z) { minmax[j].s2.Z = node.sca.Z; } } } // NODE INFO int t2Size = 0; for (int i = 0; i < sizeNode; i++) { int flag = 0; conRot[i] = false; conScale[i] = false; conTrans[i] = false; // check for constant if (minmax[i].t.Equals(minmax[i].t2)) { conTrans[i] = true; } if (minmax[i].r.Equals(minmax[i].r2)) { conRot[i] = true; } if (minmax[i].s.Equals(minmax[i].s2)) { conScale[i] = true; } if (hasTrans[i]) { flag |= 0x01000000; } if (hasRot[i]) { flag |= 0x02000000; } if (hasScale[i]) { flag |= 0x04000000; } if (conTrans[i] && hasTrans[i]) { flag |= 0x00200000; } else { flag |= 0x00080000; } if (conRot[i] && hasRot[i]) { flag |= 0x00007000; } else { flag |= 0x00005000; } if (conScale[i] && hasScale[i]) { flag |= 0x00000200; } else { flag |= 0x00000080; } flag |= 0x00000001; int hash = (int)getNodeId(vbn, nodeid[i]).boneId; //if(hash == -1) //hash = (int)FileData.crc32(getNodeId(nodeid.get(i)).name); o.writeInt(flag); // flags... o.writeInt(hash); //hash o.writeInt(t1.size()); // Offset in 1 table o.writeInt(t2Size); // Offset in 2 table // calculate size needed if (hasTrans[i]) { t1.writeFloat(minmax[i].t.X); t1.writeFloat(minmax[i].t.Y); t1.writeFloat(minmax[i].t.Z); if (!conTrans[i]) { minmax[i].t2.X -= minmax[i].t.X; minmax[i].t2.Y -= minmax[i].t.Y; minmax[i].t2.Z -= minmax[i].t.Z; t1.writeFloat(minmax[i].t2.X); t1.writeFloat(minmax[i].t2.Y); t1.writeFloat(minmax[i].t2.Z); t2Size += 6; } } if (hasRot[i]) { t1.writeFloat(minmax[i].r.X); t1.writeFloat(minmax[i].r.Y); t1.writeFloat(minmax[i].r.Z); if (!conRot[i]) { minmax[i].r2.X -= minmax[i].r.X; minmax[i].r2.Y -= minmax[i].r.Y; minmax[i].r2.Z -= minmax[i].r.Z; t1.writeFloat(minmax[i].r2.X); t1.writeFloat(minmax[i].r2.Y); t1.writeFloat(minmax[i].r2.Z); t2Size += 6; } } if (hasScale[i]) { t1.writeFloat(minmax[i].s.X); t1.writeFloat(minmax[i].s.Y); t1.writeFloat(minmax[i].s.Z); if (!conScale[i]) { minmax[i].s2.X -= minmax[i].s.X; minmax[i].s2.Y -= minmax[i].s.Y; minmax[i].s2.Z -= minmax[i].s.Z; t1.writeFloat(minmax[i].s2.X); t1.writeFloat(minmax[i].s2.Y); t1.writeFloat(minmax[i].s2.Z); t2Size += 6; } } } o.writeIntAt(o.size(), 0x18); o.writeOutput(t1); o.writeIntAt(o.size(), 0x1C); // INTERPOLATION a.setFrame(0); for (int i = 0; i < a.size(); i++) { a.nextFrame(vbn); for (int j = 0; j < nodeid.Count; j++) { Bone node = getNodeId(vbn, nodeid[j]); if (hasTrans[j] && !conTrans[j]) { t2.writeShort((int)(((node.pos.X - minmax[j].t.X) / minmax[j].t2.X) * 0xFFFF)); t2.writeShort((int)(((node.pos.Y - minmax[j].t.Y) / minmax[j].t2.Y) * 0xFFFF)); t2.writeShort((int)(((node.pos.Z - minmax[j].t.Z) / minmax[j].t2.Z) * 0xFFFF)); } if (hasRot[j] && !conRot[j]) { // float[] fix = Node.fix360(node.nrx, node.nry, node.nrz); //float[] f = CalculateRotation(node.nrx, node.nry, node.nrz); Quaternion r = node.rot; t2.writeShort((int)(((r.X - minmax[j].r.X) / minmax[j].r2.X) * 0xFFFF)); t2.writeShort((int)(((r.Y - minmax[j].r.Y) / minmax[j].r2.Y) * 0xFFFF)); t2.writeShort((int)(((r.Z - minmax[j].r.Z) / minmax[j].r2.Z) * 0xFFFF)); } if (hasScale[j] && !conScale[j]) { t2.writeShort((int)(((node.sca.X - minmax[j].s.X) / minmax[j].s2.X) * 0xFFFF)); t2.writeShort((int)(((node.sca.Y - minmax[j].s.Y) / minmax[j].s2.Y) * 0xFFFF)); t2.writeShort((int)(((node.sca.Z - minmax[j].s.Z) / minmax[j].s2.Z) * 0xFFFF)); } } if (i == 0) { o.writeShortAt(t2.size(), 0x12); } } o.writeOutput(t2); return(o.getBytes()); }
public void Render(VBN Skeleton) { if (!Runtime.renderHitboxes || Skeleton == null) { return; } if (Hitboxes.Count <= 0) { return; } GL.Enable(EnableCap.Blend); GL.Disable(EnableCap.CullFace); foreach (var pair in Hitboxes) { var h = pair.Value; if (Runtime.HiddenHitboxes.Contains(h.ID)) { continue; } Bone b = getBone(h.Bone, Skeleton); h.va = Vector3.TransformPosition(new Vector3(h.X, h.Y, h.Z), b.transform.ClearScale()); // Draw angle marker RenderHitboxAngles(h, Skeleton); GL.Color4(h.GetDisplayColor()); // Draw everything to the stencil buffer RenderTools.beginTopLevelStencil(); if (!h.IsSphere()) { h.va2 = new Vector3(h.X2, h.Y2, h.Z2); if (h.Bone != -1) { h.va2 = Vector3.TransformPosition(h.va2, b.transform.ClearScale()); } RenderTools.drawCylinder(h.va, h.va2, h.Size); } else { RenderTools.drawSphere(h.va, h.Size, 30); } // n factorial (n!) algorithm (NOT EFFICIENT) to draw subsequent hitboxes around each other. // Will work fine for the low amounts of hitboxes in smash4. if (Runtime.renderHitboxesNoOverlap) { // Remove the stencil for the already drawn hitboxes RenderTools.beginTopLevelAntiStencil(); foreach (var pair2 in Hitboxes.Reverse()) { if (pair2.Key == pair.Key) { break; // this only works because the list is sorted } var h2 = pair2.Value; if (!Runtime.HiddenHitboxes.Contains(h2.ID)) { Bone b2 = getBone(h2.Bone, Skeleton); var va = Vector3.TransformPosition(new Vector3(h2.X, h2.Y, h2.Z), b2.transform.ClearScale()); if (!h2.IsSphere()) { var va2 = new Vector3(h2.X2, h2.Y2, h2.Z2); if (h2.Bone != -1) { va2 = Vector3.TransformPosition(va2, b2.transform.ClearScale()); } RenderTools.drawCylinder(va, va2, h2.Size); } else { RenderTools.drawSphere(va, h2.Size, 30); } } } } if (Runtime.SelectedHitboxID == h.ID) { GL.Color4(Color.FromArgb(Runtime.hurtboxAlpha, Runtime.hurtboxColorSelected)); if (!h.IsSphere()) { RenderTools.drawWireframeCylinder(h.va, h.va2, h.Size); } else { RenderTools.drawWireframeSphere(h.va, h.Size, 10); } } // End stenciling and draw over all the stenciled bits RenderTools.endTopLevelStencilAndDraw(); } GL.Enable(EnableCap.CullFace); GL.Disable(EnableCap.Blend); }
public Bone(VBN v) { vbnParent = v; }
public static void createOMO(SkelAnimation a, VBN vbn, String fname) { File.WriteAllBytes(fname, createOMO(a, vbn)); }