public Animation toAnimation(VBN vbn) { Animation animation = new Animation(anim.Name); animation.FrameCount = anim.frameCount; int i = 0; foreach (Bone b in vbn.bones) { i = vbn.boneIndex(b.Text); if (i < anim.nodes.Count) { List <DAT_Animation.DATAnimTrack> tracks = anim.nodes[i]; Animation.KeyNode node = new Animation.KeyNode(b.Text); node.RotType = Animation.RotationType.EULER; foreach (DAT_Animation.DATAnimTrack track in tracks) { switch (track.type) { case DAT_Animation.AnimType.XPOS: node.XPOS = CreateKeyGroup(i, track, false); break; case DAT_Animation.AnimType.YPOS: node.YPOS = CreateKeyGroup(i, track, false); break; case DAT_Animation.AnimType.ZPOS: node.ZPOS = CreateKeyGroup(i, track, false); break; case DAT_Animation.AnimType.XROT: node.XROT = CreateKeyGroup(i, track, false); break; case DAT_Animation.AnimType.YROT: node.YROT = CreateKeyGroup(i, track, false); break; case DAT_Animation.AnimType.ZROT: node.ZROT = CreateKeyGroup(i, track, false); break; case DAT_Animation.AnimType.XSCA: node.XSCA = CreateKeyGroup(i, track, false); break; case DAT_Animation.AnimType.YSCA: node.YSCA = CreateKeyGroup(i, track, false); break; case DAT_Animation.AnimType.ZSCA: node.ZSCA = CreateKeyGroup(i, track, false); break; } } if (node.XSCA.HasAnimation() || node.YSCA.HasAnimation() || node.ZSCA.HasAnimation() || node.XPOS.HasAnimation() || node.YPOS.HasAnimation() || node.ZPOS.HasAnimation() || node.XROT.HasAnimation() || node.YROT.HasAnimation() || node.ZROT.HasAnimation()) { animation.Bones.Add(node); } } } return(animation); }
public static AnimationGroupNode Read(string filename, ResFile TargetWiiUBFRES) { FileData f = new FileData(filename); f.seek(0); f.Endian = Endianness.Little; Console.WriteLine("Reading Animations ..."); f.seek(4); // magic check int SwitchCheck = f.readInt(); //Switch version only has padded magic f.skip(4); if (SwitchCheck == 0x20202020) { // SwitchAnim2WiiU(path); //Hacky auto convert switch anims to wii u ResNSW.ResFile b = new ResNSW.ResFile(filename); AnimationGroupNode ThisAnimation = new AnimationGroupNode() { Text = "Skeleton Animations" }; TreeNode dummy = new TreeNode() { Text = "Animation Set" }; int i = 0; foreach (ResNSW.SkeletalAnim ska in b.SkeletalAnims) { Animation a = new Animation(ska.Name); ThisAnimation.Nodes.Add(a); a.FrameCount = ska.FrameCount; i++; try { foreach (Syroot.NintenTools.NSW.Bfres.BoneAnim bn in ska.BoneAnims) { FSKANode bonean = new FSKANode(bn); Animation.KeyNode bone = new Animation.KeyNode(""); a.Bones.Add(bone); if (ska.FlagsRotate == ResNSW.SkeletalAnimFlagsRotate.EulerXYZ) { bone.RotType = Animation.RotationType.EULER; } else { bone.RotType = Animation.RotationType.QUATERNION; } bone.Text = bonean.Text; for (int Frame = 0; Frame < ska.FrameCount; Frame++) { //Set base/start values for bones. //Note. BOTW doesn't use base values as it uses havok engine. Need to add option to disable these if (Frame == 0 && Runtime.HasNoAnimationBaseValues == false) { bone.XSCA.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = 1 }); bone.YSCA.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = 1 }); bone.ZSCA.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = 1 }); bone.XROT.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = bonean.rot.X }); bone.YROT.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = bonean.rot.Y }); bone.ZROT.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = bonean.rot.Z }); bone.XPOS.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = bonean.pos.X }); bone.YPOS.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = bonean.pos.Y }); bone.ZPOS.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = bonean.pos.Z }); } foreach (FSKATrack track in bonean.tracks) { Animation.KeyFrame frame = new Animation.KeyFrame(); frame.InterType = Animation.InterpolationType.HERMITE; frame.Frame = Frame; FSKAKey left = track.GetLeft(Frame); FSKAKey right = track.GetRight(Frame); float value; value = Animation.Hermite(Frame, left.frame, right.frame, 0, 0, left.unk1, right.unk1); // interpolate the value and apply switch (track.flag) { case (int)TrackType.XPOS: frame.Value = value; bone.XPOS.Keys.Add(frame); break; case (int)TrackType.YPOS: frame.Value = value; bone.YPOS.Keys.Add(frame); break; case (int)TrackType.ZPOS: frame.Value = value; bone.ZPOS.Keys.Add(frame); break; case (int)TrackType.XROT: frame.Value = value; bone.XROT.Keys.Add(frame); break; case (int)TrackType.YROT: frame.Value = value; bone.YROT.Keys.Add(frame); break; case (int)TrackType.ZROT: frame.Value = value; bone.ZROT.Keys.Add(frame); break; case (int)TrackType.XSCA: frame.Value = value; bone.XSCA.Keys.Add(frame); break; case (int)TrackType.YSCA: frame.Value = value; bone.YSCA.Keys.Add(frame); break; case (int)TrackType.ZSCA: frame.Value = value; bone.ZSCA.Keys.Add(frame); break; } } } } } catch { } } return(ThisAnimation); } else { f.eof(); TargetWiiUBFRES = new ResFile(filename); ThisAnimation = new AnimationGroupNode() { Text = "Skeleton Animations" }; TreeNode dummy = new TreeNode() { Text = "Animation Set" }; int i = 0; foreach (SkeletalAnim ska in TargetWiiUBFRES.SkeletalAnims.Values) { Animation a = new Animation(ska.Name); ThisAnimation.Nodes.Add(a); a.FrameCount = ska.FrameCount; i++; try { foreach (BoneAnim bn in ska.BoneAnims) { FSKANodeWiiU bonean = new FSKANodeWiiU(bn); Animation.KeyNode bone = new Animation.KeyNode(""); a.Bones.Add(bone); if (ska.FlagsRotate == SkeletalAnimFlagsRotate.EulerXYZ) { bone.RotType = Animation.RotationType.EULER; } else { bone.RotType = Animation.RotationType.QUATERNION; } bone.Text = bonean.Text; for (int Frame = 0; Frame < ska.FrameCount; Frame++) { //Set base/start values for bones. //Note. BOTW doesn't use base values as it uses havok engine. Need to add option to disable these if (Frame == 0 && Runtime.HasNoAnimationBaseValues == false) { bone.XSCA.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = bonean.sca.X }); bone.YSCA.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = bonean.sca.Y }); bone.ZSCA.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = bonean.sca.Z }); bone.XROT.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = bonean.rot.X }); bone.YROT.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = bonean.rot.Y }); bone.ZROT.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = bonean.rot.Z }); bone.XPOS.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = bonean.pos.X }); bone.YPOS.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = bonean.pos.Y }); bone.ZPOS.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = bonean.pos.Z }); } foreach (FSKATrack track in bonean.tracks) { Animation.KeyFrame frame = new Animation.KeyFrame(); frame.InterType = Animation.InterpolationType.HERMITE; frame.Frame = Frame; FSKAKey left = track.GetLeft(Frame); FSKAKey right = track.GetRight(Frame); float value; value = Animation.Hermite(Frame, left.frame, right.frame, 0, 0, left.unk1, right.unk1); // interpolate the value and apply switch (track.flag) { case (int)TrackType.XPOS: frame.Value = value; bone.XPOS.Keys.Add(frame); break; case (int)TrackType.YPOS: frame.Value = value; bone.YPOS.Keys.Add(frame); break; case (int)TrackType.ZPOS: frame.Value = value; bone.ZPOS.Keys.Add(frame); break; case (int)TrackType.XROT: frame.Value = value; bone.XROT.Keys.Add(frame); break; case (int)TrackType.YROT: frame.Value = value; bone.YROT.Keys.Add(frame); break; case (int)TrackType.ZROT: frame.Value = value; bone.ZROT.Keys.Add(frame); break; case (int)TrackType.XSCA: frame.Value = value; bone.XSCA.Keys.Add(frame); break; case (int)TrackType.YSCA: frame.Value = value; bone.YSCA.Keys.Add(frame); break; case (int)TrackType.ZSCA: frame.Value = value; bone.ZSCA.Keys.Add(frame); break; } } } } } catch { } } return(ThisAnimation); } }
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 AnimationGroupNode Read(string filename, ResFile TargetWiiUBFRES, BFRES bfres) { string path = filename; FileData f = new FileData(filename); int Magic = f.readInt(); if (Magic == 0x59617A30) //YAZO compressed { using (FileStream input = new FileStream(path, System.IO.FileMode.Open, FileAccess.Read, FileShare.Read)) { Yaz0Compression.Decompress(path, TEMP_FILE); path = TEMP_FILE; } } f = new FileData(path); f.seek(0); f.Endian = Endianness.Little; Console.WriteLine("Reading Animations ..."); f.seek(4); // magic check int SwitchCheck = f.readInt(); //Switch version only has padded magic f.skip(4); // SwitchAnim2WiiU(path); //Hacky auto convert switch anims to wii u Syroot.NintenTools.NSW.Bfres.ResFile b = new Syroot.NintenTools.NSW.Bfres.ResFile(path); AnimationGroupNode ThisAnimation = new AnimationGroupNode() { Text = "Bone Visual Animations" }; TreeNode dummy = new TreeNode() { Text = "Animation Set" }; int i = 0; foreach (Syroot.NintenTools.NSW.Bfres.VisibilityAnim vis in b.BoneVisibilityAnims) { Animation a = new Animation(vis.Name); ThisAnimation.Nodes.Add(a); a.FrameCount = vis.FrameCount; i++; int boneindx = 0; if (vis.Names != null) { foreach (string nm in vis.Names) //Loop through every bone. Not all have base and curve data { Animation.KeyNode bone = new Animation.KeyNode(""); a.Bones.Add(bone); bone.Text = vis.Names[boneindx]; if (boneindx < vis.BaseDataList.Length) { bool bas = vis.BaseDataList[boneindx]; if (bas == true) { bone.XSCA.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = 1 }); bone.YSCA.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = 1 }); bone.ZSCA.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = 1 }); } else { bone.XSCA.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = 0 }); bone.YSCA.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = 0 }); bone.ZSCA.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = 0 }); } } if (vis.Curves.Count != 0) { if (boneindx < vis.Curves.Count) { Syroot.NintenTools.NSW.Bfres.AnimCurve cr = vis.Curves[boneindx]; Console.WriteLine($"{vis.Name} {vis.Names[boneindx]}"); int frm = 0; foreach (bool bn in cr.KeyStepBoolData) { Animation.KeyFrame frame = new Animation.KeyFrame(); frame.InterType = Animation.InterpolationType.STEP; frame.Frame = cr.Frames[frm]; Console.WriteLine(vis.Name + " " + vis.Names[boneindx] + " " + bn); switch (bn) { case true: frame.Value = 1; bone.XSCA.Keys.Add(frame); frame.Value = 1; bone.YSCA.Keys.Add(frame); frame.Value = 1; bone.ZSCA.Keys.Add(frame); break; case false: frame.Value = 0; bone.XSCA.Keys.Add(frame); frame.Value = 0; bone.YSCA.Keys.Add(frame); frame.Value = 0; bone.ZSCA.Keys.Add(frame); break; } frm++; } } } boneindx++; } } } return(ThisAnimation); }
public static Animation readAnim(FileData d, VBN m) { int offset = d.readInt(); int nameoff = d.readInt(); d.skip(4); int fCount = d.readShort(); int animDataCount = d.readShort(); d.skip(8); Animation anim = new Animation(d.readString(nameoff, -1)); anim.FrameCount = fCount; //anim.setModel(m); d.seek(offset); int sectionOffset = d.readInt() + offset; int size = d.readInt(); // size again for (int i = 0; i < size; i++) { // System.out.print(d.readShort()); // id d.skip(4); // id and unknown d.readShort(); //left d.readShort(); //right int nameOffset = d.readInt() + offset; int dataOffset = d.readInt() + offset; if (dataOffset == offset) { i--; continue; // d.skip(8); // nameOffset = d.readInt() + 4; // dataOffset = d.readInt() + offset; } int temp = d.pos(); d.seek(dataOffset); int pos = d.pos(); int nameOff = d.readInt() + sectionOffset + (d.pos() - sectionOffset) - 4; int flags = d.readInt(); int t_type = (flags >> 0x1e) & 0x3; int r_type = (flags >> 0x1b) & 0x7; int s_type = (flags >> 0x19) & 0x3; int hasT = (flags >> 0x18) & 0x1; int hasR = (flags >> 0x17) & 0x1; int hasS = (flags >> 0x16) & 0x1; int Zfixed = (flags >> 0x15) & 0x1; int Yfixed = (flags >> 0x14) & 0x1; int Xfixed = (flags >> 0x13) & 0x1; int RZfixed = (flags >> 0x12) & 0x1; int RYfixed = (flags >> 0x11) & 0x1; int RXfixed = (flags >> 0x10) & 0x1; int SZfixed = (flags >> 0xf) & 0x1; int SYfixed = (flags >> 0xe) & 0x1; int SXfixed = (flags >> 0xd) & 0x1; int Tiso = (flags >> 0x6) & 0x1; int Riso = (flags >> 0x5) & 0x1; int Siso = (flags >> 0x4) & 0x1; Animation.KeyNode node = new Animation.KeyNode(d.readString(nameOff, -1)); anim.Bones.Add(node); node.RotType = Animation.RotationType.EULER; if (hasS == 1) { if (Siso == 1) { float iss = d.readFloat(); node.XSCA.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = iss }); node.YSCA.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = iss }); node.ZSCA.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = iss }); } else { if (SXfixed == 1) { node.XSCA.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = d.readFloat() }); } else { process(d, s_type, pos, node, "SX", false, anim); } if (SYfixed == 1) { node.YSCA.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = d.readFloat() }); } else { process(d, s_type, pos, node, "SY", false, anim); } if (SZfixed == 1) { node.ZSCA.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = d.readFloat() }); } else { process(d, s_type, pos, node, "SZ", false, anim); } } } if (hasR == 1) { if (Riso == 1) { float iss = (float)((d.readFloat()) * Math.PI / 180f); node.XROT.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = iss }); node.YROT.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = iss }); node.ZROT.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = iss }); } else { if (RXfixed == 1) { node.XROT.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = (float)(Math.PI / 180f) * (d.readFloat()) }); } else { process(d, r_type, pos, node, "RX", false, anim); } if (RYfixed == 1) { node.YROT.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = (float)(Math.PI / 180f) * (d.readFloat()) }); } else { process(d, r_type, pos, node, "RY", false, anim); } if (RZfixed == 1) { node.ZROT.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = (float)(Math.PI / 180f) * (d.readFloat()) }); } else { process(d, r_type, pos, node, "RZ", false, anim); } } } if (hasT == 1) { if (Tiso == 1) { float iss = d.readFloat(); node.XPOS.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = iss }); node.YPOS.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = iss }); node.ZPOS.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = iss }); } else { if (Xfixed == 1) { node.XPOS.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = d.readFloat() }); } else { process(d, t_type, pos, node, "X", false, anim); } if (Yfixed == 1) { node.YPOS.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = d.readFloat() }); } else { process(d, t_type, pos, node, "Y", false, anim); } if (Zfixed == 1) { node.ZPOS.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = d.readFloat() }); } else { process(d, t_type, pos, node, "Z", false, anim); } } } d.seek(temp); } return(anim); }
public static void process(FileData d, int type, int secOff, Animation.KeyNode node, String part, bool debug, Animation a) { int offset = d.readInt() + secOff; int temp = d.pos(); d.seek(offset); int max = 0; int fCount = -1; float scale = 0; float[] frame = null, step = null, tan = null; if (type == 0x1) { fCount = d.readShort(); d.skip(2); scale = d.readFloat(); float stepb = d.readFloat(); float base2 = d.readFloat(); frame = new float[fCount]; step = new float[fCount]; tan = new float[fCount]; for (int i = 0; i < fCount; i++) { frame[i] = d.readByte(); int th = d.readThree(); step[i] = base2 + ((th >> 12) & 0xfff) * stepb; tan[i] = (FileData.sign12Bit(th & 0xfff) / 32f); if (frame[i] > max) { max = (int)frame[i]; } } } if (type == 0x2) { fCount = d.readShort(); d.skip(2); scale = d.readFloat(); float stepb = d.readFloat(); float base2 = d.readFloat(); frame = new float[fCount]; step = new float[fCount]; tan = new float[fCount]; for (int i = 0; i < fCount; i++) { frame[i] = d.readShort() / 32f; step[i] = base2 + d.readShort() * stepb; tan[i] = ((short)d.readShort() / 256f); if (frame[i] > max) { max = (int)frame[i]; } } } if (type == 0x3) { //if(debug) //System.out.println(part + "\tInterpolated 12 " + Integer.toHexString(offset)); fCount = d.readShort(); d.skip(2); scale = d.readFloat(); frame = new float[fCount]; step = new float[fCount]; tan = new float[fCount]; for (int i = 0; i < fCount; i++) { frame[i] = d.readFloat(); step[i] = d.readFloat(); tan[i] = d.readFloat(); if (frame[i] > max) { max = (int)frame[i]; } } } //a.FrameCount = max; float degrad = (float)(Math.PI / 180f); if (frame != null) { for (int i = 0; i < fCount; i++) { Animation.KeyFrame f = new Animation.KeyFrame(); f.InterType = Animation.InterpolationType.HERMITE; f.Value = step[i]; f.Frame = frame[i]; f.In = tan[i]; switch (part) { case "RX": f.Value = step[i] * degrad; node.XROT.Keys.Add(f); f.Degrees = true; break; case "RY": f.Value = step[i] * degrad; node.YROT.Keys.Add(f); f.Degrees = true; break; case "RZ": f.Value = step[i] * degrad; node.ZROT.Keys.Add(f); f.Degrees = true; break; case "X": node.XPOS.Keys.Add(f); break; case "Y": node.YPOS.Keys.Add(f); break; case "Z": node.ZPOS.Keys.Add(f); break; case "SX": node.XSCA.Keys.Add(f); break; case "SY": node.YSCA.Keys.Add(f); break; case "SZ": node.ZSCA.Keys.Add(f); break; } } } if (type == 0x4) { float stepb = d.readFloat(); float base2 = d.readFloat(); for (int i = 0; i < a.FrameCount; i++) { float v = base2 + stepb * (d.readByte()); Animation.KeyFrame f = new Animation.KeyFrame(); f.InterType = Animation.InterpolationType.LINEAR; f.Value = v; f.Frame = i; switch (part) { case "RX": f.Value = v * degrad; node.XROT.Keys.Add(f); break; case "RY": f.Value = v * degrad; node.YROT.Keys.Add(f); break; case "RZ": f.Value = v * degrad; node.ZROT.Keys.Add(f); break; case "X": node.XPOS.Keys.Add(f); break; case "Y": node.YPOS.Keys.Add(f); break; case "Z": node.ZPOS.Keys.Add(f); break; case "SX": node.XSCA.Keys.Add(f); break; case "SY": node.YSCA.Keys.Add(f); break; case "SZ": node.ZSCA.Keys.Add(f); break; } } } if (type == 0x6) { for (int i = 0; i < a.FrameCount; i++) { float v = d.readFloat(); Animation.KeyFrame f = new Animation.KeyFrame(); f.InterType = Animation.InterpolationType.LINEAR; f.Value = v; f.Frame = i; switch (part) { case "RX": f.Value = v * degrad; node.XROT.Keys.Add(f); break; case "RY": f.Value = v * degrad; node.YROT.Keys.Add(f); break; case "RZ": f.Value = v * degrad; node.ZROT.Keys.Add(f); break; case "X": node.XPOS.Keys.Add(f); break; case "Y": node.YPOS.Keys.Add(f); break; case "Z": node.ZPOS.Keys.Add(f); break; case "SX": node.XSCA.Keys.Add(f); break; case "SY": node.YSCA.Keys.Add(f); break; case "SZ": node.ZSCA.Keys.Add(f); break; } } } d.seek(temp); }
public static Animation read(FileData d) { d.Endian = Endianness.Big; d.skip(4); // header OMO d.skip(4); // two shorts, idk d.skip(4); //flags? d.skip(2); int boneCount = d.readShort(); int frameCount = d.readShort(); int frameSize = d.readShort(); int offset1 = d.readInt(); // nodeOffset int offset2 = d.readInt(); // interOffset int offset3 = d.readInt(); // keyOffset SkelAnimation anim = new SkelAnimation(); anim.Tag = d; if (boneCount > offset2 / 0x10) { boneCount = offset2 / 0x10; anim.Tag = null; } // base frames // These are linked to bones via hashes d.seek(offset1); // int[] framekey = new int[boneCount]; KeyNode[] baseNode = new KeyNode[boneCount]; // Start positions for bones/nodes for (int i = 0; i < boneCount; i++) { flagsused = flagsused | d.readInt(); d.seek(d.pos() - 4); //Console.WriteLine(flagsused.ToString("x")); int flags = d.readByte(); int tFlag = d.readByte(); int rFlag = d.readByte(); int sFlag = d.readByte(); int hash = d.readInt(); // used to find the identifying bone int off1 = d.readInt() + offset2; framekey[i] = d.readInt(); bool hasTrans = (flags & 0x01) == 0x01; bool hasScale = (flags & 0x04) == 0x04; bool hasRot = (flags & 0x02) == 0x02; KeyNode node = new KeyNode(); baseNode[i] = node; node.hash = (uint)hash; int temp = d.pos(); d.seek(off1); if (hasTrans) { if (tFlag == 0x8) { // interpolated node.t_type = KeyNode.INTERPOLATED; node.t = new Vector3(d.readFloat(), d.readFloat(), d.readFloat()); node.t2 = new Vector3(d.readFloat(), d.readFloat(), d.readFloat()); } else if (tFlag == 0x20) { node.t_type = KeyNode.CONSTANT; node.t = new Vector3(d.readFloat(), d.readFloat(), d.readFloat()); } else if (tFlag == 0x4) { // entire Vector3 provided in keyframe data i.e. KEYFRAME type node.t_type = KeyNode.KEYFRAME; } } if (hasRot) { if ((rFlag & 0xF0) != 0x50 && (rFlag & 0xF0) != 0x70 && (rFlag & 0xF0) != 0x60 && (rFlag & 0xF0) != 0xA0) { //Console.WriteLine(rFlag); } if ((rFlag & 0xF0) == 0xA0) { // All data is in the keyframe for this type node.r_type = KeyNode.COMPRESSED; } if ((rFlag & 0xF0) == 0x50) { // interpolated node.r_type = KeyNode.INTERPOLATED; node.rv = new Vector3(d.readFloat(), d.readFloat(), d.readFloat()); node.rv2 = new Vector3(d.readFloat(), d.readFloat(), d.readFloat()); } if ((rFlag & 0xF0) == 0x60) { node.r_type = KeyNode.KEYFRAME; node.rv = new Vector3(d.readFloat(), d.readFloat(), d.readFloat()); node.r_extra = d.readFloat() / 65535; } if ((rFlag & 0xF0) == 0x70) { node.r_type = KeyNode.CONSTANT; node.rv = new Vector3(d.readFloat(), d.readFloat(), d.readFloat()); } } if (hasScale) { if ((sFlag & 0xF0) == 0x80) { // interpolated node.s_type = KeyNode.INTERPOLATED; node.s = new Vector3(d.readFloat(), d.readFloat(), d.readFloat()); node.s2 = new Vector3(d.readFloat(), d.readFloat(), d.readFloat()); } // TODO: investigate the difference between these if ((rFlag & 0x0F) == 0x02 || (rFlag & 0x0F) == 0x03) { // constant node.s_type = KeyNode.CONSTANT; node.s = new Vector3(d.readFloat(), d.readFloat(), d.readFloat()); } } d.seek(temp); } // Interpolated type below here is always a set translation/rotation/scale // from the coords specified with the bone node above Animation a = new Animation("Anim"); a.Tag = anim.Tag; a.FrameCount = frameCount; d.seek(offset3); for (int j = 0; j < boneCount; j++) { string bid = ""; int hash = -1; if (!MainForm.Hashes.ids.TryGetValue(baseNode[j].hash, out bid)) { hash = (int)baseNode[j].hash; } Animation.KeyNode n = new Animation.KeyNode(bid); n.Hash = hash; a.Bones.Add(n); n.Type = Animation.BoneType.NORMAL; /*foreach (ModelContainer con in Runtime.ModelContainers) * if (con.VBN != null) * bid = con.VBN.getBone(baseNode[j].hash) == null ? "" : con.VBN.getBone(baseNode[j].hash).Text;*/ for (int i = 0; i < a.FrameCount; i++) { d.seek(offset3 + frameSize * i + framekey[j]); if (baseNode[j].t_type == KeyNode.INTERPOLATED) { float i1 = ((float)d.readShort() / 0xffff); float i2 = ((float)d.readShort() / 0xffff); float i3 = ((float)d.readShort() / 0xffff); float x = baseNode[j].t.X + (baseNode[j].t2.X * (i1)); float y = baseNode[j].t.Y + (baseNode[j].t2.Y * (i2)); float z = baseNode[j].t.Z + (baseNode[j].t2.Z * (i3)); //node.t = new Vector3(x, y, z); // Translation n.XPOS.Keys.Add(new Animation.KeyFrame(x, i)); n.YPOS.Keys.Add(new Animation.KeyFrame(y, i)); n.ZPOS.Keys.Add(new Animation.KeyFrame(z, i)); } else if (baseNode[j].t_type == KeyNode.CONSTANT) { //node.t = baseNode[j].t; n.XPOS.Keys.Add(new Animation.KeyFrame(baseNode[j].t.X, i)); n.YPOS.Keys.Add(new Animation.KeyFrame(baseNode[j].t.Y, i)); n.ZPOS.Keys.Add(new Animation.KeyFrame(baseNode[j].t.Z, i)); } else if (baseNode[j].t_type == 2) { float x = d.readFloat(); float y = d.readFloat(); float z = d.readFloat(); //node.t = new Vector3(x, y, z); n.XPOS.Keys.Add(new Animation.KeyFrame(x, i)); n.YPOS.Keys.Add(new Animation.KeyFrame(y, i)); n.ZPOS.Keys.Add(new Animation.KeyFrame(z, i)); } if (baseNode[j].r_type == KeyNode.COMPRESSED) { // There are 64 bits present for each node of this rot type // The format is: 20bits * 3 of encoded floats, and 4 bits of flags // The flags describe which 3 components of the quaternion are being presented int b1 = d.readByte(); int b2 = d.readByte(); int b3 = d.readByte(); int b4 = d.readByte(); int b5 = d.readByte(); int b6 = d.readByte(); int b7 = d.readByte(); int b8 = d.readByte(); // Capture 20 bits at a time of the raw data int f1 = (b1 << 12) | (b2 << 4) | ((b3 & 0xF0) >> 4); int f2 = ((b3 & 0xF) << 16) | (b4 << 8) | b5; int f3 = (b6 << 12) | (b7 << 4) | ((b8 & 0xF0) >> 4); int flags = b8 & 0xF; Quaternion r = new Quaternion(); switch (flags) { case 0: // y, z, w provided r.Y = encodedRot10ToQuaternionComponent(f1); r.Z = encodedRot10ToQuaternionComponent(f2); r.W = encodedRot10ToQuaternionComponent(f3); r.X = (float)Math.Sqrt(Math.Abs(1 - (r.Y * r.Y + r.Z * r.Z + r.W * r.W))); break; case 1: // x, z, w provided r.X = encodedRot10ToQuaternionComponent(f1); r.Z = encodedRot10ToQuaternionComponent(f2); r.W = encodedRot10ToQuaternionComponent(f3); r.Y = (float)Math.Sqrt(Math.Abs(1 - (r.X * r.X + r.Z * r.Z + r.W * r.W))); break; case 2: // x, y, w provided r.X = encodedRot10ToQuaternionComponent(f1); r.Y = encodedRot10ToQuaternionComponent(f2); r.W = encodedRot10ToQuaternionComponent(f3); r.Z = (float)Math.Sqrt(Math.Abs(1 - (r.X * r.X + r.Y * r.Y + r.W * r.W))); break; case 3: // x, y, z, provided r.X = encodedRot10ToQuaternionComponent(f1); r.Y = encodedRot10ToQuaternionComponent(f2); r.Z = encodedRot10ToQuaternionComponent(f3); r.W = (float)Math.Sqrt(Math.Abs(1 - (r.X * r.X + r.Y * r.Y + r.Z * r.Z))); break; default: Console.WriteLine("Unknown rotation type3 flags: " + flags); break; } n.RotType = Animation.RotationType.QUATERNION; n.XROT.Keys.Add(new Animation.KeyFrame(r.X, i)); n.YROT.Keys.Add(new Animation.KeyFrame(r.Y, i)); n.ZROT.Keys.Add(new Animation.KeyFrame(r.Z, i)); n.WROT.Keys.Add(new Animation.KeyFrame(r.W, i)); } else if (baseNode[j].r_type == KeyNode.INTERPOLATED) { float i1 = ((float)d.readShort() / (0xffff)); float i2 = ((float)d.readShort() / (0xffff)); float i3 = ((float)d.readShort() / (0xffff)); float x = baseNode[j].rv.X + (baseNode[j].rv2.X * (i1)); float y = baseNode[j].rv.Y + (baseNode[j].rv2.Y * (i2)); float z = baseNode[j].rv.Z + (baseNode[j].rv2.Z * (i3)); float w = (float)Math.Sqrt(Math.Abs(1 - (x * x + y * y + z * z))); Quaternion r = new Quaternion(new Vector3(x, y, z), w); r.Normalize(); n.RotType = Animation.RotationType.QUATERNION; n.XROT.Keys.Add(new Animation.KeyFrame(r.X, i)); n.YROT.Keys.Add(new Animation.KeyFrame(r.Y, i)); n.ZROT.Keys.Add(new Animation.KeyFrame(r.Z, i)); n.WROT.Keys.Add(new Animation.KeyFrame(r.W, i)); } else if (baseNode[j].r_type == KeyNode.KEYFRAME) { float scale = d.readShort() * baseNode[j].r_extra; float x = baseNode[j].rv.X; float y = baseNode[j].rv.Y; float z = baseNode[j].rv.Z + scale; float w = rot6CalculateW(x, y, z); Quaternion r = new Quaternion(x, y, z, w); n.RotType = Animation.RotationType.QUATERNION; n.XROT.Keys.Add(new Animation.KeyFrame(r.X, i)); n.YROT.Keys.Add(new Animation.KeyFrame(r.Y, i)); n.ZROT.Keys.Add(new Animation.KeyFrame(r.Z, i)); n.WROT.Keys.Add(new Animation.KeyFrame(r.W, i)); } else { float x = baseNode[j].rv.X; float y = baseNode[j].rv.Y; float z = baseNode[j].rv.Z; float w = (float)Math.Sqrt(Math.Abs(1 - (x * x + y * y + z * z))); Quaternion r = new Quaternion(baseNode[j].rv, w); r.Normalize(); n.RotType = Animation.RotationType.QUATERNION; n.XROT.Keys.Add(new Animation.KeyFrame(r.X, i)); n.YROT.Keys.Add(new Animation.KeyFrame(r.Y, i)); n.ZROT.Keys.Add(new Animation.KeyFrame(r.Z, i)); n.WROT.Keys.Add(new Animation.KeyFrame(r.W, i)); } if (baseNode[j].s_type == KeyNode.INTERPOLATED) { float i1 = ((float)d.readShort() / (0xffff)); float i2 = ((float)d.readShort() / (0xffff)); float i3 = ((float)d.readShort() / (0xffff)); float x = baseNode[j].s.X + (baseNode[j].s2.X * (i1)); float y = baseNode[j].s.Y + (baseNode[j].s2.Y * (i2)); float z = baseNode[j].s.Z + (baseNode[j].s2.Z * (i3)); //node.s = new Vector3(x, y, z); n.XSCA.Keys.Add(new Animation.KeyFrame(x, i)); n.YSCA.Keys.Add(new Animation.KeyFrame(y, i)); n.ZSCA.Keys.Add(new Animation.KeyFrame(z, i)); } else { //node.s = baseNode[j].s; n.XSCA.Keys.Add(new Animation.KeyFrame(baseNode[j].s.X, i)); n.YSCA.Keys.Add(new Animation.KeyFrame(baseNode[j].s.Y, i)); n.ZSCA.Keys.Add(new Animation.KeyFrame(baseNode[j].s.Z, i)); } } } return(a); }
public static byte[] CreateOMOFromAnimation(Animation a, VBN vbn) { if (vbn == null || a == null) { return new byte[] { } } ; // Test Actual Bones //------------------------- List <Animation.KeyNode> toRem = new List <Animation.KeyNode>(); for (int j = 0; j < a.Bones.Count; j++) { Animation.KeyNode keynode = ((Animation.KeyNode)a.Bones[j]); Bone b = vbn.getBone(keynode.Text); if (b == null) { toRem.Add(keynode); } } foreach (Animation.KeyNode r in toRem) { Console.WriteLine("Removing " + r.Text); a.Bones.Remove(r); } //------------------------- 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(a.Bones.Count); // numOfNodes o.writeShort(a.FrameCount); // frame size o.writeShort(0); // frame start ?? o.writeInt(0); o.writeInt(0); o.writeInt(0); o.writeIntAt(o.size(), 0x14); // ASSESSMENT Vector3[] maxT = new Vector3[a.Bones.Count], minT = new Vector3[a.Bones.Count]; Vector4[] maxR = new Vector4[a.Bones.Count], minR = new Vector4[a.Bones.Count]; Vector3[] maxS = new Vector3[a.Bones.Count], minS = new Vector3[a.Bones.Count]; bool[] hasScale = new bool[a.Bones.Count]; bool[] hasTrans = new bool[a.Bones.Count]; bool[] hasRot = new bool[a.Bones.Count]; bool[] conScale = new bool[a.Bones.Count]; bool[] conTrans = new bool[a.Bones.Count]; bool[] conRot = new bool[a.Bones.Count]; a.SetFrame(0); List <List <Bone> > Frames = new List <List <Bone> >(); { for (int j = 0; j < a.Bones.Count; j++) { Animation.KeyNode keynode = ((Animation.KeyNode)a.Bones[j]); if (keynode.XPOS.HasAnimation() || keynode.YPOS.HasAnimation() || keynode.ZPOS.HasAnimation()) { hasTrans[j] = true; } if (keynode.XROT.HasAnimation()) { hasRot[j] = true; } if (keynode.XSCA.HasAnimation() || keynode.YSCA.HasAnimation() || keynode.ZSCA.HasAnimation()) { hasScale[j] = true; } maxT[j] = new Vector3(-999f, -999f, -999f); minT[j] = new Vector3(999f, 999f, 999f); maxS[j] = new Vector3(-999f, -999f, -999f); minS[j] = new Vector3(999f, 999f, 999f); maxR[j] = new Vector4(-999f, -999f, -999f, -999f); minR[j] = new Vector4(999f, 999f, 999f, 999f); foreach (Animation.KeyFrame key in keynode.XPOS.Keys) { maxT[j].X = Math.Max(maxT[j].X, key.Value); minT[j].X = Math.Min(minT[j].X, key.Value); } foreach (Animation.KeyFrame key in keynode.YPOS.Keys) { maxT[j].Y = Math.Max(maxT[j].Y, key.Value); minT[j].Y = Math.Min(minT[j].Y, key.Value); } foreach (Animation.KeyFrame key in keynode.ZPOS.Keys) { maxT[j].Z = Math.Max(maxT[j].Z, key.Value); minT[j].Z = Math.Min(minT[j].Z, key.Value); } foreach (Animation.KeyFrame key in keynode.XSCA.Keys) { maxS[j].X = Math.Max(maxS[j].X, key.Value); minS[j].X = Math.Min(minS[j].X, key.Value); } foreach (Animation.KeyFrame key in keynode.YSCA.Keys) { maxS[j].Y = Math.Max(maxS[j].Y, key.Value); minS[j].Y = Math.Min(minS[j].Y, key.Value); } foreach (Animation.KeyFrame key in keynode.ZSCA.Keys) { maxS[j].Z = Math.Max(maxS[j].Z, key.Value); minS[j].Z = Math.Min(minS[j].Z, key.Value); } Bone b = vbn.getBone(keynode.Text); for (int i = 0; i < a.FrameCount; i++) { Quaternion r = new Quaternion(); if (keynode.RotType == Animation.RotationType.QUATERNION) { Animation.KeyFrame[] x = keynode.XROT.GetFrame(i); Animation.KeyFrame[] y = keynode.YROT.GetFrame(i); Animation.KeyFrame[] z = keynode.ZROT.GetFrame(i); Animation.KeyFrame[] w = keynode.WROT.GetFrame(i); 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 == i) { r = q1; } else if (x[1].Frame == i) { r = q2; } else { r = Quaternion.Slerp(q1, q2, (i - x[0].Frame) / (x[1].Frame - x[0].Frame)); } } else if (keynode.RotType == Animation.RotationType.EULER) { float x = keynode.XROT.HasAnimation() ? keynode.XROT.GetValue(i) : b.rotation[0]; float y = keynode.YROT.HasAnimation() ? keynode.YROT.GetValue(i) : b.rotation[1]; float z = keynode.ZROT.HasAnimation() ? keynode.ZROT.GetValue(i) : b.rotation[2]; r = Animation.EulerToQuat(z, y, x); } r.Normalize(); maxR[j].X = Math.Max(maxR[j].X, r.X); minR[j].X = Math.Min(minR[j].X, r.X); maxR[j].Y = Math.Max(maxR[j].Y, r.Y); minR[j].Y = Math.Min(minR[j].Y, r.Y); maxR[j].Z = Math.Max(maxR[j].Z, r.Z); minR[j].Z = Math.Min(minR[j].Z, r.Z); } //if (b == null)continue; if (b != null) { if (maxT[j].X == -999) { maxT[j].X = b.position[0]; } if (maxT[j].Y == -999) { maxT[j].Y = b.position[1]; } if (maxT[j].Z == -999) { maxT[j].Z = b.position[2]; } if (minT[j].X == -999) { minT[j].X = b.position[0]; } if (minT[j].Y == -999) { minT[j].Y = b.position[1]; } if (minT[j].Z == -999) { minT[j].Z = b.position[2]; } if (maxS[j].X == -999) { maxS[j].X = b.scale[0]; } if (maxS[j].Y == -999) { maxS[j].Y = b.scale[1]; } if (maxS[j].Z == -999) { maxS[j].Z = b.scale[2]; } if (minS[j].X == -999) { minS[j].X = b.scale[0]; } if (minS[j].Y == -999) { minS[j].Y = b.scale[1]; } if (minS[j].Z == -999) { minS[j].Z = b.scale[2]; } } } } //TODO: Euler Rotation Values /*VBN tempvbn = new VBN(); * a.SetFrame(0); * for (int i = 0; i < a.FrameCount; i++) * { * //Frames.Add(new List<Bone>()); * for (int j = 0; j < a.Bones.Count; j++) * { * Animation.KeyNode keynode = a.Bones[j]; * Bone b = vbn.getBone(keynode.Text); * //if(b == null) continue; * maxR[j].X = Math.Max(maxR[j].X, b.rot.X); * minR[j].X = Math.Min(minR[j].X, b.rot.X); * maxR[j].Y = Math.Max(maxR[j].Y, b.rot.Y); * minR[j].Y = Math.Min(minR[j].Y, b.rot.Y); * maxR[j].Z = Math.Max(maxR[j].Z, b.rot.Z); * minR[j].Z = Math.Min(minR[j].Z, b.rot.Z); * * Bone f1 = new Bone(tempvbn); * f1.pos = b.pos; * f1.rot = b.rot; * f1.sca = b.sca; * //Frames[i].Add(f1); * } * a.NextFrame(vbn); * }*/ // NODE INFO int t2Size = 0; for (int i = 0; i < a.Bones.Count; i++) { int flag = 0; conRot[i] = false; conScale[i] = false; conTrans[i] = false; // check for constant if (maxT[i].Equals(minT[i])) { conTrans[i] = true; } if (maxR[i].Equals(minR[i])) { conRot[i] = true; } if (maxS[i].Equals(minS[i])) { 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; //uint id = 999; Bone b = vbn.getBone(a.Bones[i].Text); int hash = -1; if (MainForm.Hashes.names.ContainsKey(a.Bones[i].Text)) { hash = (int)MainForm.Hashes.names[a.Bones[i].Text]; } else { if (b != null) { hash = (int)b.boneId; } else { continue; } } //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(minT[i].X); t1.writeFloat(minT[i].Y); t1.writeFloat(minT[i].Z); if (!conTrans[i]) { maxT[i].X -= minT[i].X; maxT[i].Y -= minT[i].Y; maxT[i].Z -= minT[i].Z; t1.writeFloat(maxT[i].X); t1.writeFloat(maxT[i].Y); t1.writeFloat(maxT[i].Z); t2Size += 6; } } if (hasRot[i]) { t1.writeFloat(minR[i].X); t1.writeFloat(minR[i].Y); t1.writeFloat(minR[i].Z); if (!conRot[i]) { maxR[i].X -= minR[i].X; maxR[i].Y -= minR[i].Y; maxR[i].Z -= minR[i].Z; t1.writeFloat(maxR[i].X); t1.writeFloat(maxR[i].Y); t1.writeFloat(maxR[i].Z); t2Size += 6; } } if (hasScale[i]) { t1.writeFloat(minS[i].X); t1.writeFloat(minS[i].Y); t1.writeFloat(minS[i].Z); if (!conScale[i]) { maxS[i].X -= minS[i].X; maxS[i].Y -= minS[i].Y; maxS[i].Z -= minS[i].Z; t1.writeFloat(maxS[i].X); t1.writeFloat(maxS[i].Y); t1.writeFloat(maxS[i].Z); t2Size += 6; } } } o.writeIntAt(o.size(), 0x18); o.writeOutput(t1); o.writeIntAt(o.size(), 0x1C); // INTERPOLATION a.SetFrame(0); bool go = true; for (int i = 0; i < a.FrameCount; i++) { //a.NextFrame(vbn); for (int j = 0; j < a.Bones.Count; j++) { Bone node = vbn.getBone(a.Bones[j].Text); Animation.KeyNode anode = a.Bones[j]; //if (node == null) continue; if (hasTrans[j] && !conTrans[j]) { t2.writeShort((int)(((anode.XPOS.GetValue(i) - minT[j].X) / maxT[j].X) * 0xFFFF)); t2.writeShort((int)(((anode.YPOS.GetValue(i) - minT[j].Y) / maxT[j].Y) * 0xFFFF)); t2.writeShort((int)(((anode.ZPOS.GetValue(i) - minT[j].Z) / maxT[j].Z) * 0xFFFF)); } if (hasRot[j] && !conRot[j]) { Quaternion r = new Quaternion(); if (anode.RotType == Animation.RotationType.QUATERNION) { Animation.KeyFrame[] x = anode.XROT.GetFrame(i); Animation.KeyFrame[] y = anode.YROT.GetFrame(i); Animation.KeyFrame[] z = anode.ZROT.GetFrame(i); Animation.KeyFrame[] w = anode.WROT.GetFrame(i); 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 == i) { r = q1; } else if (x[1].Frame == i) { r = q2; } else { r = Quaternion.Slerp(q1, q2, (i - x[0].Frame) / (x[1].Frame - x[0].Frame)); } } else if (anode.RotType == Animation.RotationType.EULER) { float x = anode.XROT.HasAnimation() ? anode.XROT.GetValue(i) : node.rotation[0]; float y = anode.YROT.HasAnimation() ? anode.YROT.GetValue(i) : node.rotation[1]; float z = anode.ZROT.HasAnimation() ? anode.ZROT.GetValue(i) : node.rotation[2]; r = Animation.EulerToQuat(z, y, x); } r.Normalize(); t2.writeShort((int)(((r.X - minR[j].X) / maxR[j].X) * 0xFFFF)); t2.writeShort((int)(((r.Y - minR[j].Y) / maxR[j].Y) * 0xFFFF)); t2.writeShort((int)(((r.Z - minR[j].Z) / maxR[j].Z) * 0xFFFF)); } if (hasScale[j] && !conScale[j]) { t2.writeShort((int)(((anode.XSCA.GetValue(i) - minS[j].X) / maxS[j].X) * 0xFFFF)); t2.writeShort((int)(((anode.YSCA.GetValue(i) - minS[j].Y) / maxS[j].Y) * 0xFFFF)); t2.writeShort((int)(((anode.ZSCA.GetValue(i) - minS[j].Z) / maxS[j].Z) * 0xFFFF)); } } if (go) { o.writeShortAt(t2.size(), 0x12); go = false; } } o.writeOutput(t2); return(o.getBytes()); } }
public static byte[] CreateOMOFromAnimation(Animation a, VBN vbn) { 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(a.Bones.Count); // numOfNodes o.writeShort(a.FrameCount); // frame size o.writeShort(0); // frame start ?? o.writeInt(0); o.writeInt(0); o.writeInt(0); o.writeIntAt(o.size(), 0x14); // ASSESSMENT Vector3[] maxT = new Vector3[a.Bones.Count], minT = new Vector3[a.Bones.Count]; Vector4[] maxR = new Vector4[a.Bones.Count], minR = new Vector4[a.Bones.Count]; Vector3[] maxS = new Vector3[a.Bones.Count], minS = new Vector3[a.Bones.Count]; bool[] hasScale = new bool[a.Bones.Count]; bool[] hasTrans = new bool[a.Bones.Count]; bool[] hasRot = new bool[a.Bones.Count]; bool[] conScale = new bool[a.Bones.Count]; bool[] conTrans = new bool[a.Bones.Count]; bool[] conRot = new bool[a.Bones.Count]; a.SetFrame(0); //for (int i = 0; i < a.FrameCount; i++) { //a.NextFrame(vbn); for (int j = 0; j < a.Bones.Count; j++) { Animation.KeyNode keynode = ((Animation.KeyNode)a.Bones[j]); if (keynode.XPOS.HasAnimation() || keynode.YPOS.HasAnimation() || keynode.ZPOS.HasAnimation()) { hasTrans[j] = true; } if (keynode.XROT.HasAnimation()) { hasRot[j] = true; } if (keynode.XSCA.HasAnimation() || keynode.YSCA.HasAnimation() || keynode.ZSCA.HasAnimation()) { hasScale[j] = true; } maxT[j] = new Vector3(-999f, -999f, -999f); minT[j] = new Vector3(999f, 999f, 999f); maxS[j] = new Vector3(-999f, -999f, -999f); minS[j] = new Vector3(999f, 999f, 999f); maxR[j] = new Vector4(-999f, -999f, -999f, -999f); minR[j] = new Vector4(999f, 999f, 999f, 999f); foreach (Animation.KeyFrame key in keynode.XPOS.Keys) { maxT[j].X = Math.Max(maxT[j].X, key.Value); minT[j].X = Math.Min(minT[j].X, key.Value); } foreach (Animation.KeyFrame key in keynode.YPOS.Keys) { maxT[j].Y = Math.Max(maxT[j].Y, key.Value); minT[j].Y = Math.Min(minT[j].Y, key.Value); } foreach (Animation.KeyFrame key in keynode.ZPOS.Keys) { maxT[j].Z = Math.Max(maxT[j].Z, key.Value); minT[j].Z = Math.Min(minT[j].Z, key.Value); } foreach (Animation.KeyFrame key in keynode.XSCA.Keys) { maxS[j].X = Math.Max(maxS[j].X, key.Value); minS[j].X = Math.Min(minS[j].X, key.Value); } foreach (Animation.KeyFrame key in keynode.YSCA.Keys) { maxS[j].Y = Math.Max(maxS[j].Y, key.Value); minS[j].Y = Math.Min(minS[j].Y, key.Value); } foreach (Animation.KeyFrame key in keynode.ZSCA.Keys) { maxS[j].Z = Math.Max(maxS[j].Z, key.Value); minS[j].Z = Math.Min(minS[j].Z, key.Value); } //TODO: Euler Rotation Values a.SetFrame(0); Bone b = vbn.getBone(keynode.Text); if (b == null) { continue; } for (int i = 0; i < a.FrameCount; i++) { maxR[j].X = Math.Max(maxR[j].X, b.rot.X); minR[j].X = Math.Min(minR[j].X, b.rot.X); maxR[j].Y = Math.Max(maxR[j].Y, b.rot.Y); minR[j].Y = Math.Min(minR[j].Y, b.rot.Y); maxR[j].Z = Math.Max(maxR[j].Z, b.rot.Z); minR[j].Z = Math.Min(minR[j].Z, b.rot.Z); a.NextFrame(vbn); } if (b != null) { if (maxT[j].X == -999) { maxT[j].X = b.position[0]; } if (maxT[j].Y == -999) { maxT[j].Y = b.position[1]; } if (maxT[j].Z == -999) { maxT[j].Z = b.position[2]; } if (minT[j].X == -999) { minT[j].X = b.position[0]; } if (minT[j].Y == -999) { minT[j].Y = b.position[1]; } if (minT[j].Z == -999) { minT[j].Z = b.position[2]; } if (maxS[j].X == -999) { maxS[j].X = b.scale[0]; } if (maxS[j].Y == -999) { maxS[j].Y = b.scale[1]; } if (maxS[j].Z == -999) { maxS[j].Z = b.scale[2]; } if (minS[j].X == -999) { minS[j].X = b.scale[0]; } if (minS[j].Y == -999) { minS[j].Y = b.scale[1]; } if (minS[j].Z == -999) { minS[j].Z = b.scale[2]; } } } } // NODE INFO int t2Size = 0; for (int i = 0; i < a.Bones.Count; i++) { int flag = 0; conRot[i] = false; conScale[i] = false; conTrans[i] = false; // check for constant if (maxT[i].Equals(minT[i])) { conTrans[i] = true; } if (maxR[i].Equals(minR[i])) { conRot[i] = true; } if (maxS[i].Equals(minS[i])) { 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; //uint id = 999; Bone b = vbn.getBone(a.Bones[i].Text); int hash = -1; if (b != null) { hash = (int)b.boneId; } else { continue; } //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(minT[i].X); t1.writeFloat(minT[i].Y); t1.writeFloat(minT[i].Z); if (!conTrans[i]) { maxT[i].X -= minT[i].X; maxT[i].Y -= minT[i].Y; maxT[i].Z -= minT[i].Z; t1.writeFloat(maxT[i].X); t1.writeFloat(maxT[i].Y); t1.writeFloat(maxT[i].Z); t2Size += 6; } } if (hasRot[i]) { t1.writeFloat(minR[i].X); t1.writeFloat(minR[i].Y); t1.writeFloat(minR[i].Z); if (!conRot[i]) { maxR[i].X -= minR[i].X; maxR[i].Y -= minR[i].Y; maxR[i].Z -= minR[i].Z; t1.writeFloat(maxR[i].X); t1.writeFloat(maxR[i].Y); t1.writeFloat(maxR[i].Z); t2Size += 6; } } if (hasScale[i]) { t1.writeFloat(minS[i].X); t1.writeFloat(minS[i].Y); t1.writeFloat(minS[i].Z); if (!conScale[i]) { maxS[i].X -= minS[i].X; maxS[i].Y -= minS[i].Y; maxS[i].Z -= minS[i].Z; t1.writeFloat(maxS[i].X); t1.writeFloat(maxS[i].Y); t1.writeFloat(maxS[i].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.FrameCount; i++) { //Console.WriteLine("Workin on" + i); a.NextFrame(vbn); for (int j = 0; j < a.Bones.Count; j++) { Bone node = vbn.getBone(a.Bones[j].Text); if (node == null) { continue; } if (hasTrans[j] && !conTrans[j]) { t2.writeShort((int)(((node.pos.X - minT[j].X) / maxT[j].X) * 0xFFFF)); t2.writeShort((int)(((node.pos.Y - minT[j].Y) / maxT[j].Y) * 0xFFFF)); t2.writeShort((int)(((node.pos.Z - minT[j].Z) / maxT[j].Z) * 0xFFFF)); } if (hasRot[j] && !conRot[j]) { Quaternion r = node.rot; t2.writeShort((int)(((r.X - minR[j].X) / maxR[j].X) * 0xFFFF)); t2.writeShort((int)(((r.Y - minR[j].Y) / maxR[j].Y) * 0xFFFF)); t2.writeShort((int)(((r.Z - minR[j].Z) / maxR[j].Z) * 0xFFFF)); } if (hasScale[j] && !conScale[j]) { t2.writeShort((int)(((node.sca.X - minS[j].X) / maxS[j].X) * 0xFFFF)); t2.writeShort((int)(((node.sca.Y - minS[j].Y) / maxS[j].Y) * 0xFFFF)); t2.writeShort((int)(((node.sca.Z - minS[j].Z) / maxS[j].Z) * 0xFFFF)); } } if (i == 0) { o.writeShortAt(t2.size(), 0x12); } } //Console.WriteLine("Saving"); o.writeOutput(t2); return(o.getBytes()); }
public void Read(ResFile TargetWiiUBFRES, AnimationGroupNode ThisAnimation, ResNSW.ResFile b) { Console.WriteLine("Reading Skeleton Animations ..."); if (b != null) { TreeNode SkeletonAnimation = new TreeNode() { Text = "Skeleton Animations" }; ThisAnimation.Nodes.Add(SkeletonAnimation); TreeNode dummy = new TreeNode() { Text = "Animation Set" }; int i = 0; foreach (ResNSW.SkeletalAnim ska in b.SkeletalAnims) { if (i == 0) { dummy = new TreeNode() { Text = "Animation Set " + "0 - 100" }; SkeletonAnimation.Nodes.Add(dummy); } if (i == 100) { dummy = new TreeNode() { Text = "Animation Set " + "100 - 200" }; SkeletonAnimation.Nodes.Add(dummy); } if (i == 200) { dummy = new TreeNode() { Text = "Animation Set " + "200 - 300" }; SkeletonAnimation.Nodes.Add(dummy); } if (i == 300) { dummy = new TreeNode() { Text = "Animation Set " + "300 - 400" }; SkeletonAnimation.Nodes.Add(dummy); } if (i == 400) { dummy = new TreeNode() { Text = "Animation Set " + "400 - 500" }; SkeletonAnimation.Nodes.Add(dummy); } if (i == 500) { dummy = new TreeNode() { Text = "Animation Set " + "500 - 600" }; SkeletonAnimation.Nodes.Add(dummy); } if (i == 600) { dummy = new TreeNode() { Text = "Animation Set " + "600 - 700" }; SkeletonAnimation.Nodes.Add(dummy); } if (i == 700) { dummy = new TreeNode() { Text = "Animation Set " + "700 - 800" }; SkeletonAnimation.Nodes.Add(dummy); } if (i == 800) { dummy = new TreeNode() { Text = "Animation Set " + "800 - 900" }; SkeletonAnimation.Nodes.Add(dummy); } if (i == 900) { dummy = new TreeNode() { Text = "Animation Set " + "900 - 1000" }; SkeletonAnimation.Nodes.Add(dummy); } if (i == 1000) { dummy = new TreeNode() { Text = "Animation Set " + "1000+" }; SkeletonAnimation.Nodes.Add(dummy); } Animation a = new Animation(ska.Name); SkeletonAnimations.Add(a); a.FrameCount = ska.FrameCount; if (i >= 0 && i < 100) { SkeletonAnimation.Nodes[0].Nodes.Add(a); } if (i >= 100 && i < 200) { SkeletonAnimation.Nodes[1].Nodes.Add(a); } if (i >= 200 && i < 300) { SkeletonAnimation.Nodes[2].Nodes.Add(a); } if (i >= 300 && i < 400) { SkeletonAnimation.Nodes[3].Nodes.Add(a); } if (i >= 400 && i < 500) { SkeletonAnimation.Nodes[4].Nodes.Add(a); } if (i >= 500 && i < 600) { SkeletonAnimation.Nodes[5].Nodes.Add(a); } if (i >= 600 && i < 700) { SkeletonAnimation.Nodes[6].Nodes.Add(a); } if (i >= 700 && i < 800) { SkeletonAnimation.Nodes[7].Nodes.Add(a); } if (i >= 800 && i < 900) { SkeletonAnimation.Nodes[8].Nodes.Add(a); } if (i >= 900 && i < 1000) { SkeletonAnimation.Nodes[9].Nodes.Add(a); } i++; try { foreach (ResNSW.BoneAnim bn in ska.BoneAnims) { FSKANode bonean = new FSKANode(bn); Animation.KeyNode bone = new Animation.KeyNode(""); a.Bones.Add(bone); if (ska.FlagsRotate == ResNSW.SkeletalAnimFlagsRotate.EulerXYZ) { bone.RotType = Animation.RotationType.EULER; } else { bone.RotType = Animation.RotationType.QUATERNION; } bone.Text = bonean.Text; for (int Frame = 0; Frame < ska.FrameCount; Frame++) { //Set base/start values for bones. //Note. BOTW doesn't use base values as it uses havok engine. Need to add option to disable these if (Frame == 0) { if (bn.FlagsBase.HasFlag(ResNSW.BoneAnimFlagsBase.Scale)) { bone.XSCA.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = bonean.sca.X }); bone.YSCA.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = bonean.sca.Y }); bone.ZSCA.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = bonean.sca.Z }); } if (bn.FlagsBase.HasFlag(ResNSW.BoneAnimFlagsBase.Rotate)) { bone.XROT.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = bonean.rot.X }); bone.YROT.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = bonean.rot.Y }); bone.ZROT.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = bonean.rot.Z }); bone.WROT.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = bonean.rot.W }); } if (bn.FlagsBase.HasFlag(ResNSW.BoneAnimFlagsBase.Translate)) { bone.XPOS.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = bonean.pos.X }); bone.YPOS.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = bonean.pos.Y }); bone.ZPOS.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = bonean.pos.Z }); } } foreach (FSKATrack track in bonean.tracks) { Animation.KeyFrame frame = new Animation.KeyFrame(); frame.InterType = Animation.InterpolationType.HERMITE; frame.Frame = Frame; FSKAKey left = track.GetLeft(Frame); FSKAKey right = track.GetRight(Frame); float value; value = Animation.Hermite(Frame, left.frame, right.frame, 0, 0, left.unk1, right.unk1); // interpolate the value and apply switch (track.flag) { case (int)TrackType.XPOS: frame.Value = value; bone.XPOS.Keys.Add(frame); break; case (int)TrackType.YPOS: frame.Value = value; bone.YPOS.Keys.Add(frame); break; case (int)TrackType.ZPOS: frame.Value = value; bone.ZPOS.Keys.Add(frame); break; case (int)TrackType.XROT: frame.Value = value; bone.XROT.Keys.Add(frame); break; case (int)TrackType.YROT: frame.Value = value; bone.YROT.Keys.Add(frame); break; case (int)TrackType.ZROT: frame.Value = value; bone.ZROT.Keys.Add(frame); break; case (int)TrackType.XSCA: frame.Value = value; bone.XSCA.Keys.Add(frame); break; case (int)TrackType.YSCA: frame.Value = value; bone.YSCA.Keys.Add(frame); break; case (int)TrackType.ZSCA: frame.Value = value; bone.ZSCA.Keys.Add(frame); break; } } } } } catch { } } } else { TreeNode SkeletonAnimation = new TreeNode() { Text = "Skeleton Animations" }; ThisAnimation.Nodes.Add(SkeletonAnimation); TreeNode dummy = new TreeNode() { Text = "Animation Set" }; int i = 0; foreach (SkeletalAnim ska in TargetWiiUBFRES.SkeletalAnims.Values) { if (i == 0) { dummy = new TreeNode() { Text = "Animation Set " + "0 - 100" }; SkeletonAnimation.Nodes.Add(dummy); } if (i == 100) { dummy = new TreeNode() { Text = "Animation Set " + "100 - 200" }; SkeletonAnimation.Nodes.Add(dummy); } if (i == 200) { dummy = new TreeNode() { Text = "Animation Set " + "200 - 300" }; SkeletonAnimation.Nodes.Add(dummy); } if (i == 300) { dummy = new TreeNode() { Text = "Animation Set " + "300 - 400" }; SkeletonAnimation.Nodes.Add(dummy); } if (i == 400) { dummy = new TreeNode() { Text = "Animation Set " + "400 - 500" }; SkeletonAnimation.Nodes.Add(dummy); } if (i == 500) { dummy = new TreeNode() { Text = "Animation Set " + "500 - 600" }; SkeletonAnimation.Nodes.Add(dummy); } if (i == 600) { dummy = new TreeNode() { Text = "Animation Set " + "600 - 700" }; SkeletonAnimation.Nodes.Add(dummy); } if (i == 700) { dummy = new TreeNode() { Text = "Animation Set " + "700 - 800" }; SkeletonAnimation.Nodes.Add(dummy); } if (i == 800) { dummy = new TreeNode() { Text = "Animation Set " + "800 - 900" }; SkeletonAnimation.Nodes.Add(dummy); } if (i == 900) { dummy = new TreeNode() { Text = "Animation Set " + "900 - 1000" }; SkeletonAnimation.Nodes.Add(dummy); } if (i == 1000) { dummy = new TreeNode() { Text = "Animation Set " + "1000+" }; SkeletonAnimation.Nodes.Add(dummy); } Animation a = new Animation(ska.Name); SkeletonAnimations.Add(a); if (i >= 0 && i < 100) { SkeletonAnimation.Nodes[0].Nodes.Add(a); } if (i >= 100 && i < 200) { SkeletonAnimation.Nodes[1].Nodes.Add(a); } if (i >= 200 && i < 300) { SkeletonAnimation.Nodes[2].Nodes.Add(a); } if (i >= 300 && i < 400) { SkeletonAnimation.Nodes[3].Nodes.Add(a); } if (i >= 400 && i < 500) { SkeletonAnimation.Nodes[4].Nodes.Add(a); } if (i >= 500 && i < 600) { SkeletonAnimation.Nodes[5].Nodes.Add(a); } if (i >= 600 && i < 700) { SkeletonAnimation.Nodes[6].Nodes.Add(a); } if (i >= 700 && i < 800) { SkeletonAnimation.Nodes[7].Nodes.Add(a); } if (i >= 800 && i < 900) { SkeletonAnimation.Nodes[8].Nodes.Add(a); } if (i >= 900 && i < 1000) { SkeletonAnimation.Nodes[9].Nodes.Add(a); } a.FrameCount = ska.FrameCount; i++; try { foreach (BoneAnim bn in ska.BoneAnims) { FSKANodeWiiU bonean = new FSKANodeWiiU(bn); Animation.KeyNode bone = new Animation.KeyNode(""); a.Bones.Add(bone); if (ska.FlagsRotate == SkeletalAnimFlagsRotate.EulerXYZ) { bone.RotType = Animation.RotationType.EULER; } else { bone.RotType = Animation.RotationType.QUATERNION; } bone.Text = bonean.Text; for (int Frame = 0; Frame < ska.FrameCount; Frame++) { //Set base/start values for bones. //Note. BOTW doesn't use base values as it uses havok engine. Need to add option to disable these if (Frame == 0) { if (bn.FlagsBase.HasFlag(BoneAnimFlagsBase.Scale)) { bone.XSCA.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = bonean.sca.X }); bone.YSCA.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = bonean.sca.Y }); bone.ZSCA.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = bonean.sca.Z }); } if (bn.FlagsBase.HasFlag(BoneAnimFlagsBase.Rotate)) { bone.XROT.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = bonean.rot.X }); bone.YROT.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = bonean.rot.Y }); bone.ZROT.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = bonean.rot.Z }); bone.WROT.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = bonean.rot.W }); } if (bn.FlagsBase.HasFlag(BoneAnimFlagsBase.Translate)) { bone.XPOS.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = bonean.pos.X }); bone.YPOS.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = bonean.pos.Y }); bone.ZPOS.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = bonean.pos.Z }); } } foreach (FSKATrack track in bonean.tracks) { Animation.KeyFrame frame = new Animation.KeyFrame(); frame.InterType = Animation.InterpolationType.HERMITE; frame.Frame = Frame; FSKAKey left = track.GetLeft(Frame); FSKAKey right = track.GetRight(Frame); float value; value = Animation.Hermite(Frame, left.frame, right.frame, 0, 0, left.unk1, right.unk1); // interpolate the value and apply switch (track.flag) { case (int)TrackType.XPOS: frame.Value = value; bone.XPOS.Keys.Add(frame); break; case (int)TrackType.YPOS: frame.Value = value; bone.YPOS.Keys.Add(frame); break; case (int)TrackType.ZPOS: frame.Value = value; bone.ZPOS.Keys.Add(frame); break; case (int)TrackType.XROT: frame.Value = value; bone.XROT.Keys.Add(frame); break; case (int)TrackType.YROT: frame.Value = value; bone.YROT.Keys.Add(frame); break; case (int)TrackType.ZROT: frame.Value = value; bone.ZROT.Keys.Add(frame); break; case (int)TrackType.XSCA: frame.Value = value; bone.XSCA.Keys.Add(frame); break; case (int)TrackType.YSCA: frame.Value = value; bone.YSCA.Keys.Add(frame); break; case (int)TrackType.ZSCA: frame.Value = value; bone.ZSCA.Keys.Add(frame); break; } } } } } catch { } } } Console.WriteLine("Saving " + SkeletonAnimations.Count + " anims"); foreach (var anim in SkeletonAnimations) { anim.SaveAsExpeditedAnim(); } }
public static AnimationGroupNode Read(string filename) { bchHeader header = new bchHeader(); FileData f = new FileData(filename); f.Endian = System.IO.Endianness.Little; f.skip(4); header.backwardCompatibility = f.readByte(); header.forwardCompatibility = f.readByte(); header.version = f.readUShort(); header.mainHeaderOffset = f.readInt(); header.stringTableOffset = f.readInt(); header.gpuCommandsOffset = f.readInt(); header.dataOffset = f.readInt(); if (header.backwardCompatibility > 0x20) { header.dataExtendedOffset = f.readInt(); } header.relocationTableOffset = f.readInt(); header.mainHeaderLength = f.readInt(); header.stringTableLength = f.readInt(); header.gpuCommandsLength = f.readInt(); header.dataLength = f.readInt(); if (header.backwardCompatibility > 0x20) { header.dataExtendedLength = f.readInt(); } header.relocationTableLength = f.readInt(); header.uninitializedDataSectionLength = f.readInt(); header.uninitializedDescriptionSectionLength = f.readInt(); if (header.backwardCompatibility > 7) { header.flags = f.readUShort(); header.addressCount = f.readUShort(); } // Relocation table for (int i = 0; i < header.relocationTableLength; i += 4) { f.seek(header.relocationTableOffset + i); int val = f.readInt(); int off = val & 0x1FFFFFF; byte flag = (byte)(val >> 25); switch (flag) { case 0: f.seek((off * 4) + header.mainHeaderOffset); f.writeInt((off * 4) + header.mainHeaderOffset, f.readInt() + header.mainHeaderOffset); break; case 1: f.seek(off + header.mainHeaderOffset); f.writeInt((off) + header.mainHeaderOffset, f.readInt() + header.stringTableOffset); break; case 2: f.seek((off * 4) + header.mainHeaderOffset); f.writeInt((off * 4) + header.mainHeaderOffset, f.readInt() + header.gpuCommandsOffset); break; case 0xc: f.seek((off * 4) + header.mainHeaderOffset); f.writeInt((off * 4) + header.mainHeaderOffset, f.readInt() + header.dataOffset); break; } } // Content Header f.seek(header.mainHeaderOffset); bchContentHeader content = new bchContentHeader(); { content.modelsPointerTableOffset = f.readInt(); content.modelsPointerTableEntries = f.readInt(); content.modelsNameOffset = f.readInt(); content.materialsPointerTableOffset = f.readInt(); content.materialsPointerTableEntries = f.readInt(); content.materialsNameOffset = f.readInt(); content.shadersPointerTableOffset = f.readInt(); content.shadersPointerTableEntries = f.readInt(); content.shadersNameOffset = f.readInt(); content.texturesPointerTableOffset = f.readInt(); content.texturesPointerTableEntries = f.readInt(); content.texturesNameOffset = f.readInt(); content.materialsLUTPointerTableOffset = f.readInt(); content.materialsLUTPointerTableEntries = f.readInt(); content.materialsLUTNameOffset = f.readInt(); content.lightsPointerTableOffset = f.readInt(); content.lightsPointerTableEntries = f.readInt(); content.lightsNameOffset = f.readInt(); content.camerasPointerTableOffset = f.readInt(); content.camerasPointerTableEntries = f.readInt(); content.camerasNameOffset = f.readInt(); content.fogsPointerTableOffset = f.readInt(); content.fogsPointerTableEntries = f.readInt(); content.fogsNameOffset = f.readInt(); content.skeletalAnimationsPointerTableOffset = f.readInt(); content.skeletalAnimationsPointerTableEntries = f.readInt(); content.skeletalAnimationsNameOffset = f.readInt(); content.materialAnimationsPointerTableOffset = f.readInt(); content.materialAnimationsPointerTableEntries = f.readInt(); content.materialAnimationsNameOffset = f.readInt(); content.visibilityAnimationsPointerTableOffset = f.readInt(); content.visibilityAnimationsPointerTableEntries = f.readInt(); content.visibilityAnimationsNameOffset = f.readInt(); content.lightAnimationsPointerTableOffset = f.readInt(); content.lightAnimationsPointerTableEntries = f.readInt(); content.lightAnimationsNameOffset = f.readInt(); content.cameraAnimationsPointerTableOffset = f.readInt(); content.cameraAnimationsPointerTableEntries = f.readInt(); content.cameraAnimationsNameOffset = f.readInt(); content.fogAnimationsPointerTableOffset = f.readInt(); content.fogAnimationsPointerTableEntries = f.readInt(); content.fogAnimationsNameOffset = f.readInt(); content.scenePointerTableOffset = f.readInt(); content.scenePointerTableEntries = f.readInt(); content.sceneNameOffset = f.readInt(); } //Skeletal animation AnimationGroupNode ThisAnimation = new AnimationGroupNode() { Text = filename }; for (int index1 = 0; index1 < content.skeletalAnimationsPointerTableEntries; index1++)// { f.seek(content.skeletalAnimationsPointerTableOffset + (index1 * 4)); int dataOffset = f.readInt(); f.seek(dataOffset); string skeletalAnimationName = f.readString(f.readInt(), -1); int animationFlags = f.readInt(); //int skeletalAnimationloopMode = f.readByte(); //pas ça du tout float skeletalAnimationframeSize = f.readFloat(); int boneTableOffset = f.readInt(); int boneTableEntries = f.readInt(); int metaDataPointerOffset = f.readInt(); //Runtime.Animations.Add(skeletalAnimationName, a); //MainForm.animNode.Nodes.Add(skeletalAnimationName); Animation a = new Animation(skeletalAnimationName); ThisAnimation.Nodes.Add(a); for (int i = 0; i < boneTableEntries; i++) { f.seek(boneTableOffset + (i * 4)); int offset = f.readInt(); Animation.KeyNode bone = new Animation.KeyNode(""); a.Bones.Add(bone); f.seek(offset); bone.Text = f.readString(f.readInt(), -1); //Console.WriteLine("Bone Name: " + bone.name); int animationTypeFlags = f.readInt(); uint flags = (uint)f.readInt(); OSegmentType segmentType = (OSegmentType)((animationTypeFlags >> 16) & 0xf); //Debug.WriteLine(bone.Text + " " + flags.ToString("x")); switch (segmentType) { case OSegmentType.transform: f.seek(offset + 0xC); //Console.WriteLine(f.pos().ToString("x") + " " + flags.ToString("x")); uint notExistMask = 0x10000; uint constantMask = 0x40; for (int j = 0; j < 3; j++) { for (int axis = 0; axis < 3; axis++) { bool notExist = (flags & notExistMask) > 0; bool constant = (flags & constantMask) > 0; //Console.WriteLine(notExist + " " + constant); Animation.KeyGroup group = new Animation.KeyGroup(); //frame.exists = !notExist; if (!notExist) { if (constant) { Animation.KeyFrame frame = new Animation.KeyFrame(); frame.InterType = Animation.InterpolationType.LINEAR; frame.Value = f.readFloat(); frame.Frame = 0; group.Keys.Add(frame); } else { int frameOffset = f.readInt(); int position = f.pos(); f.seek(frameOffset); float c = 0; //Debug.WriteLine(j + " " + axis + " " + bone.Text); getAnimationKeyFrame(f, group, out c); if (c > a.FrameCount) { a.FrameCount = (int)c; } f.seek(position); } } else { f.seek(f.pos() + 0x04); } bone.RotType = Animation.RotationType.EULER; if (j == 0) { switch (axis) { case 0: bone.XSCA = group; break; case 1: bone.YSCA = group; break; case 2: bone.ZSCA = group; break; } } else if (j == 1) { switch (axis) { case 0: bone.XROT = group; break; case 1: bone.YROT = group; break; case 2: bone.ZROT = group; break; } } else if (j == 2) { switch (axis) { case 0: bone.XPOS = group; break; case 1: bone.YPOS = group; break; case 2: bone.ZPOS = group; break; } } notExistMask <<= 1; constantMask <<= 1; } if (j == 1) { constantMask <<= 1; } } break; /*case OSegmentType.transformQuaternion: * bone.isFrameFormat = true; * * int scaleOffset = f.readInt(); * int rotationOffset = f.readInt(); * int translationOffset = f.readInt(); * * if ((flags & 0x20) == 0) * { * bone.scale.exists = true; * f.seek(scaleOffset); * * if ((flags & 4) > 0) * { * bone.scale.vector.Add(new Vector4( * f.readFloat(), * f.readFloat(), * f.readFloat(), * 0)); * } * else * { * bone.scale.startFrame = f.readFloat(); * bone.scale.endFrame = f.readFloat(); * * int scaleFlags = f.readInt(); * int scaleDataOffset = f.readInt(); * int scaleEntries = f.readInt(); * * f.seek(scaleDataOffset); * for (int j = 0; j < scaleEntries; j++) * { * bone.scale.vector.Add(new Vector4( * f.readFloat(), * f.readFloat(), * f.readFloat(), * 0)); * } * } * } * * if ((flags & 0x10) == 0) * { * bone.rotationQuaternion.exists = true; * f.seek(rotationOffset); * * if ((flags & 2) > 0) * { * bone.rotationQuaternion.vector.Add(new Vector4( * f.readFloat(), * f.readFloat(), * f.readFloat(), * f.readFloat())); * } * else * { * bone.rotationQuaternion.startFrame = f.readFloat(); * bone.rotationQuaternion.endFrame = f.readFloat(); * * int rotationFlags = f.readInt(); * int rotationDataOffset = f.readInt(); * int rotationEntries = f.readInt(); * * f.seek(rotationDataOffset); * for (int j = 0; j < rotationEntries; j++) * { * bone.rotationQuaternion.vector.Add(new Vector4( * f.readFloat(), * f.readFloat(), * f.readFloat(), * f.readFloat())); * } * } * } * * if ((flags & 8) == 0) * { * bone.translation.exists = true; * f.seek(translationOffset); * * if ((flags & 1) > 0) * { * bone.translation.vector.Add(new Vector4( * f.readFloat(), * f.readFloat(), * f.readFloat(), * 0)); * } * else * { * bone.translation.startFrame = f.readFloat(); * bone.translation.endFrame = f.readFloat(); * * int translationFlags = f.readInt(); * int translationDataOffset = f.readInt(); * int translationEntries = f.readInt(); * * f.seek(translationDataOffset); * for (int j = 0; j < translationEntries; j++) * { * bone.translation.vector.Add(new Vector4( * f.readFloat(), * f.readFloat(), * f.readFloat(), * 0)); * } * } * } * * break; * case OSegmentType.transformMatrix: * bone.isFullBakedFormat = true; * * f.readInt(); * f.readInt(); * int matrixOffset = f.readInt(); * int entries = f.readInt(); * * f.seek(matrixOffset); * for (int j = 0; j < entries; j++) * { * OMatrix transform = new OMatrix(); * transform.M11 = f.readFloat(); * transform.M21 = f.readFloat(); * transform.M31 = f.readFloat(); * transform.M41 = f.readFloat(); * * transform.M12 = f.readFloat(); * transform.M22 = f.readFloat(); * transform.M32 = f.readFloat(); * transform.M42 = f.readFloat(); * * transform.M13 = f.readFloat(); * transform.M23 = f.readFloat(); * transform.M33 = f.readFloat(); * transform.M43 = f.readFloat(); * * bone.transform.Add(transform); * } * * break;*/ default: throw new Exception(string.Format("BCH: Unknow Segment Type {0} on Skeletal Animation bone {1}! STOP!", segmentType, bone.Text)); } //skeletalAnimation.bone.Add(bone); } } //return a; return(ThisAnimation); }
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); }
private static void writeKey(StreamWriter file, Animation.KeyGroup keys, Animation.KeyNode rt, int size, string type) { file.WriteLine("animData {\n input time;\n output linear;\n weighted 1;\n preInfinity constant;\n postInfinity constant;\n keys {"); if (((Animation.KeyFrame)keys.Keys[0]).InterType == Animation.InterpolationType.CONSTANT) { size = 1; } foreach (Animation.KeyFrame key in keys.Keys) { float v = 0; float scale = 1; switch (type) { case "translateX": v = key.Value; break; case "translateY": v = key.Value; break; case "translateZ": v = key.Value; break; case "rotateX": if (rt.RotType == Animation.RotationType.EULER) { v = key.Value * (float)(180f / Math.PI); } if (rt.RotType == Animation.RotationType.QUATERNION) { Quaternion q = new Quaternion(rt.XROT.GetValue(key.Frame), rt.YROT.GetValue(key.Frame), rt.ZROT.GetValue(key.Frame), rt.WROT.GetValue(key.Frame)); v = quattoeul(q).X *(float)(180f / Math.PI); } scale = (float)(180f / Math.PI); break; case "rotateY": if (rt.RotType == Animation.RotationType.EULER) { v = key.Value * (float)(180f / Math.PI); } if (rt.RotType == Animation.RotationType.QUATERNION) { Quaternion q = new Quaternion(rt.XROT.GetValue(key.Frame), rt.YROT.GetValue(key.Frame), rt.ZROT.GetValue(key.Frame), rt.WROT.GetValue(key.Frame)); v = quattoeul(q).Y *(float)(180f / Math.PI); } scale = (float)(180f / Math.PI); break; case "rotateZ": if (rt.RotType == Animation.RotationType.EULER) { v = key.Value * (float)(180f / Math.PI); } if (rt.RotType == Animation.RotationType.QUATERNION) { Quaternion q = new Quaternion(rt.XROT.GetValue(key.Frame), rt.YROT.GetValue(key.Frame), rt.ZROT.GetValue(key.Frame), rt.WROT.GetValue(key.Frame)); v = quattoeul(q).Z *(float)(180f / Math.PI); } scale = (float)(180f / Math.PI); break; case "scaleX": v = key.Value; break; case "scaleY": v = key.Value; break; case "scaleZ": v = key.Value; break; } file.WriteLine(" " + (key.Frame + 1) + " {0:N6} fixed fixed 1 1 0 " + key.In * scale + " 1 " + (key.Out != -1 ? key.Out : key.In) * scale + " 1;", v); } file.WriteLine(" }"); }
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("}"); } if (ac == 0) { file.WriteLine("anim " + b.Text + " 0 0 0;"); } } else { file.WriteLine("anim " + b.Text + " 0 0 0;"); } } } }
private void Render(object sender, PaintEventArgs e) { if (!ReadyToRender) { return; } glViewport.MakeCurrent(); GL.LoadIdentity(); GL.Viewport(glViewport.ClientRectangle); // Push all attributes so we don't have to clean up later GL.PushAttrib(AttribMask.AllAttribBits); // clear the gf buffer GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit | ClearBufferMask.StencilBufferBit); // use fixed function pipeline for drawing background and floor grid GL.UseProgram(0); if (MeshList.treeView1.SelectedNode != null) { if (MeshList.treeView1.SelectedNode is BCH_Texture) { GL.PopAttrib(); BCH_Texture tex = ((BCH_Texture)MeshList.treeView1.SelectedNode); RenderTools.DrawTexturedQuad(tex.display, tex.Width, tex.Height, true, true, true, true, false, true); glViewport.SwapBuffers(); return; } if (MeshList.treeView1.SelectedNode is NUT_Texture) { GL.PopAttrib(); NUT_Texture tex = ((NUT_Texture)MeshList.treeView1.SelectedNode); RenderTools.DrawTexturedQuad(((NUT)tex.Parent).draw[tex.HASHID], tex.Width, tex.Height, true, true, true, true, false, true); glViewport.SwapBuffers(); return; } } if (Runtime.renderBackGround) { // background uses different matrices GL.MatrixMode(MatrixMode.Modelview); GL.LoadIdentity(); GL.MatrixMode(MatrixMode.Projection); GL.LoadIdentity(); RenderTools.RenderBackground(); } // Camera Update // ------------------------------------------------------------- GL.MatrixMode(MatrixMode.Projection); if (glViewport.ClientRectangle.Contains(glViewport.PointToClient(Cursor.Position)) && glViewport.Focused && CurrentMode == Mode.Normal && !TransformTool.hit) { Camera.Update(); //if (cameraPosForm != null && !cameraPosForm.IsDisposed) // cameraPosForm.updatePosition(); } try { if (OpenTK.Input.Mouse.GetState() != null) { Camera.mouseSLast = OpenTK.Input.Mouse.GetState().WheelPrecise; } } catch { } Matrix4 matrix = Camera.getMVPMatrix(); GL.MatrixMode(MatrixMode.Modelview); GL.LoadMatrix(ref matrix); // Floor // ------------------------------------------------------------- if (Runtime.renderFloor) { RenderTools.drawFloor(); } // Shadows // ------------------------------------------------------------- if (Runtime.drawModelShadow) { CalculateLightSource(); // update light matrix and setup shadowmap rendering GL.MatrixMode(MatrixMode.Modelview); GL.LoadMatrix(ref lightMatrix); GL.Enable(EnableCap.DepthTest); GL.Viewport(0, 0, sw, sh); GL.BindFramebuffer(FramebufferTarget.Framebuffer, sfb); foreach (ModelContainer m in draw) { m.RenderShadow(Camera, 0, Matrix4.Zero, Camera.getMVPMatrix()); } // reset matrices and viewport for model rendering again GL.BindFramebuffer(FramebufferTarget.Framebuffer, 0); GL.LoadMatrix(ref matrix); GL.Viewport(glViewport.ClientRectangle); } // render models into hdr buffer // ------------------------------------------------------------- if (Runtime.useDepthTest) { GL.Enable(EnableCap.DepthTest); GL.DepthFunc(DepthFunction.Lequal); } else { GL.Disable(EnableCap.DepthTest); } GL.Enable(EnableCap.DepthTest); // Models // ------------------------------------------------------------- //frameTime.Start(); if (Runtime.renderModel || Runtime.renderModelWireframe) { foreach (TreeNode m in draw) { if (m is ModelContainer) { ((ModelContainer)m).Render(Camera, 0, Matrix4.Zero, Camera.getMVPMatrix()); } } } if (ViewComboBox.SelectedIndex == 1) { foreach (TreeNode m in draw) { if (m is ModelContainer) { ((ModelContainer)m).RenderPoints(Camera); } } } //GL.BindFramebuffer(FramebufferTarget.Framebuffer, 0); /*// render gaussian blur stuff * if (Runtime.drawQuadBlur) * DrawQuadBlur(); * * // render full screen quad for post processing * if (Runtime.drawQuadFinalOutput) * DrawQuadFinalOutput();*/ // use fixed function pipeline again for area lights, lvd, bones, hitboxes, etc SetupFixedFunctionRendering(); /*// draw path.bin * if (Runtime.renderPath) * DrawPathDisplay(); * * // area light bounding boxes should intersect stage geometry and not render on top * if (Runtime.drawAreaLightBoundingBoxes) * DrawAreaLightBoundingBoxes();*/ // clear depth buffer so stuff will render on top of the models GL.Clear(ClearBufferMask.DepthBufferBit); if (Runtime.renderLVD) { _lvd.Render(); } if (Runtime.renderBones) { foreach (ModelContainer m in draw) { m.RenderBones(); } } // ACMD if (ParamManager != null && Runtime.renderHurtboxes && draw.Count > 0 && (draw[0] is ModelContainer)) { ParamManager.RenderHurtboxes(Frame, scriptId, ACMDScript, ((ModelContainer)draw[0]).GetVBN()); } if (ACMDScript != null && draw.Count > 0 && (draw[0] is ModelContainer)) { ACMDScript.Render(((ModelContainer)draw[0]).GetVBN()); } //Debug.WriteLine(frameTime.getAverageRenderTime()); // Bone Transform Tool if (ViewComboBox.SelectedIndex == 2) { if (modeBone.Checked) { TransformTool.Render(Camera, new Ray(Camera, glViewport)); if (TransformTool.state == 1) { CurrentMode = Mode.Selection; } else { CurrentMode = Mode.Normal; } } if (TransformTool.HasChanged()) { if (Animation != null && TransformTool.b != null) { // get the node group for the current bone in animation Animation.KeyNode ThisNode = null; foreach (Animation.KeyNode node in Animation.Bones) { if (node.Text.Equals(TransformTool.b.Text)) { // found ThisNode = node; break; } } if (ThisNode == null) { ThisNode = new Animation.KeyNode(TransformTool.b.Text); Animation.Bones.Add(ThisNode); } // update or add the key frame ThisNode.SetKeyFromBone((float)currentFrame.Value, TransformTool.b); } } } // Mouse selection // ------------------------------------------------------------- if (ViewComboBox.SelectedIndex == 1) { try { if (CurrentMode == Mode.Normal && OpenTK.Input.Mouse.GetState().IsButtonDown(OpenTK.Input.MouseButton.Right)) { CurrentMode = Mode.Selection; Vector2 m = GetMouseOnViewport(); sx1 = m.X; sy1 = m.Y; } } catch { } if (CurrentMode == Mode.Selection) { if (!OpenTK.Input.Mouse.GetState().IsButtonDown(OpenTK.Input.MouseButton.Right)) { checkSelect(); CurrentMode = Mode.Normal; } GL.MatrixMode(MatrixMode.Modelview); GL.PushMatrix(); GL.LoadIdentity(); Vector2 m = GetMouseOnViewport(); GL.Color3(Color.Black); GL.LineWidth(2f); GL.Begin(PrimitiveType.LineLoop); GL.Vertex2(sx1, sy1); GL.Vertex2(m.X, sy1); GL.Vertex2(m.X, m.Y); GL.Vertex2(sx1, m.Y); GL.End(); GL.Color3(Color.White); GL.LineWidth(1f); GL.Begin(PrimitiveType.LineLoop); GL.Vertex2(sx1, sy1); GL.Vertex2(m.X, sy1); GL.Vertex2(m.X, m.Y); GL.Vertex2(sx1, m.Y); GL.End(); GL.PopMatrix(); } } /*if (CurrentMode == Mode.Photoshoot) * { * freezeCamera = false; * if (Keyboard.GetState().IsKeyDown(Key.W) && Mouse.GetState().IsButtonDown(MouseButton.Left)) * { * shootX = this.PointToClient(Cursor.Position).X; * shootY = this.PointToClient(Cursor.Position).Y; * freezeCamera = true; * } * // Hold on to your pants, boys * RenderTools.DrawPhotoshoot(glViewport, shootX, shootY, shootWidth, shootHeight); * }*/ GL.PopAttrib(); glViewport.SwapBuffers(); }