public static void WriteKeyData(Animation.KeyGroup group, FileOutput boneHeader, FileOutput keyData, FileOutput d_Main3, int start, ref int track) { if (group.keys.Count == 1) { boneHeader.WriteFloat(group.keys[0].Value); } else if (group.keys.Count == 0) { boneHeader.WriteInt(0); } else { int off = (group.keys.Count * 4); boneHeader.WriteOffset(start + keyData.Size(), d_Main3); // bone offset keyData.WriteFloat(0); keyData.WriteFloat(group.FrameCount); keyData.WriteInt(track++ << 16); // track keyData.WriteInt((group.keys.Count << 16) | 0x0701); // 7 is quantinization and 1 is linear interpolation float minv = 999, maxv = -999; float minf = 999, maxf = -999; foreach (Animation.KeyFrame key in group.keys) { minv = Math.Min(key.Value, minv); maxv = Math.Max(key.Value, maxv); minf = Math.Min(key.Frame, minf); maxf = Math.Max(key.Frame, maxf); } maxv -= minv; keyData.WriteFloat(maxv / 0xFFFFF); // value scale keyData.WriteFloat(minv); // value offset keyData.WriteFloat(1f); // frame scale keyData.WriteFloat(minf); // frame offset keyData.WriteOffset(start + keyData.Size() + 4, d_Main3); // useless flags foreach (Animation.KeyFrame key in group.keys) { keyData.WriteInt((((int)(((key.Value - minv) / (maxv)) * 0xFFFFF)) << 12) | (((int)(key.Frame - minf)) & 0xFFF)); } } //------ }
private static Animation.KeyGroup CreateKeyGroup(int i, DAT_Animation.DATAnimTrack track, bool rotation) { Animation.KeyGroup group = new Animation.KeyGroup(); int size = track.keys.Count; int time = 0; float cvalue = 0, ctan = 0; for (int f = 0; f < size; f++) { while (track.keys[f].interpolationType == DAT_Animation.InterpolationType.HermiteCurve) { f++; } DAT_Animation.KeyNode no = track.keys[f]; DAT_Animation.KeyNode curve = track.keys[f + 1 >= track.keys.Count ? 0 : f + 1]; if (curve.interpolationType == DAT_Animation.InterpolationType.HermiteCurve) { cvalue = no.value; ctan = curve.tan; group.keys.Add(new Animation.KeyFrame() { weighted = true, Frame = time, Value = cvalue, In = no.tan, Out = ctan, interType = Animation.InterpolationType.Hermite }); //file.WriteLine(" " + (time + 1) + " {0:N6} fixed fixed 1 1 0 {1:N6} 1 {2:N6} 1;", cvalue * (rotation ? 180 / (float)Math.PI : 1), no.tan, ctan); } else { switch (no.interpolationType) { case DAT_Animation.InterpolationType.Hermite: { cvalue = no.value; ctan = no.tan; group.keys.Add(new Animation.KeyFrame() { weighted = true, Frame = time, Value = cvalue, In = ctan, Out = ctan, interType = Animation.InterpolationType.Hermite }); //file.WriteLine(" " + (time + 1) + " {0:N6} fixed fixed 1 1 0 {1:N6} 1 {2:N6} 1;", cvalue * (rotation ? 180 / (float)Math.PI : 1), ctan, ctan); } break; case DAT_Animation.InterpolationType.HermiteValue: { cvalue = no.value; ctan = 0; group.keys.Add(new Animation.KeyFrame() { weighted = true, Frame = time, Value = cvalue, In = ctan, Out = ctan, interType = Animation.InterpolationType.Hermite }); //file.WriteLine(" " + (time + 1) + " {0:N6} fixed fixed 1 1 0 {1:N6} 1 {2:N6} 1;", cvalue * (rotation ? 180 / (float)Math.PI : 1), ctan, ctan); } break; case DAT_Animation.InterpolationType.Step: { cvalue = no.value; group.keys.Add(new Animation.KeyFrame() { weighted = false, Frame = time, Value = cvalue, interType = Animation.InterpolationType.Step }); //file.WriteLine(" " + (time + 1) + " {0:N6} fixed fixed 1 1 0 0 1 0 1;", cvalue * (rotation ? 180 / (float)Math.PI : 1)); } break; case DAT_Animation.InterpolationType.Linear: { cvalue = no.value; group.keys.Add(new Animation.KeyFrame() { weighted = false, Frame = time, Value = cvalue, interType = Animation.InterpolationType.Linear }); //file.WriteLine(" " + (time + 1) + " {0:N6} linear linear 1 1 0", cvalue * (rotation ? 180 / (float)Math.PI : 1)); } break; } } time += (int)no.frame; } return(group); }
private static void getAnimationKeyFrame(FileData input, Animation.KeyGroup group, out float endFrame) { float startFrame = input.ReadFloat(); endFrame = input.ReadFloat(); uint frameFlags = (uint)input.ReadInt(); //Debug.WriteLine(frameFlags.ToString("x")); //int preRepeat = (RenderBase.ORepeatMethod)(frameFlags & 0xf); //int postRepeat = (RenderBase.ORepeatMethod)((frameFlags >> 8) & 0xf); uint segmentFlags = (uint)input.ReadInt(); int interpolation = ((int)segmentFlags & 0xf); uint quantization = ((segmentFlags >> 8) & 0xff); uint entries = segmentFlags >> 16; float valueScale = input.ReadFloat(); float valueOffset = input.ReadFloat(); float frameScale = input.ReadFloat(); float frameOffset = input.ReadFloat(); uint offset = (uint)input.ReadInt(); if (offset < input.Size()) { input.Seek((int)offset); } for (int key = 0; key < entries; key++) { Animation.KeyFrame keyFrame = new Animation.KeyFrame(); //Console.WriteLine(quantization); switch (quantization) { /*case RenderBase.OSegmentQuantization.hermite128: * keyFrame.frame = input.ReadSingle(); * keyFrame.value = input.ReadSingle(); * keyFrame.inSlope = input.ReadSingle(); * keyFrame.outSlope = input.ReadSingle(); * break; * case RenderBase.OSegmentQuantization.hermite64: * uint h64Value = input.ReadUInt32(); * keyFrame.frame = h64Value & 0xfff; * keyFrame.value = h64Value >> 12; * keyFrame.inSlope = input.ReadInt16() / 256f; * keyFrame.outSlope = input.ReadInt16() / 256f; * break; * case RenderBase.OSegmentQuantization.hermite48: * keyFrame.frame = input.ReadByte(); * keyFrame.value = input.ReadUInt16(); * byte slope0 = input.ReadByte(); * byte slope1 = input.ReadByte(); * byte slope2 = input.ReadByte(); * keyFrame.inSlope = IOUtils.signExtend(slope0 | ((slope1 & 0xf) << 8), 12) / 32f; * keyFrame.outSlope = IOUtils.signExtend((slope1 >> 4) | (slope2 << 4), 12) / 32f; * break; * case RenderBase.OSegmentQuantization.unifiedHermite96: * keyFrame.frame = input.ReadSingle(); * keyFrame.value = input.ReadSingle(); * keyFrame.inSlope = input.ReadSingle(); * keyFrame.outSlope = keyFrame.inSlope; * break; * case RenderBase.OSegmentQuantization.unifiedHermite48: * keyFrame.frame = input.ReadUInt16() / 32f; * keyFrame.value = input.ReadUInt16(); * keyFrame.inSlope = input.ReadInt16() / 256f; * keyFrame.outSlope = keyFrame.inSlope; * break; * case RenderBase.OSegmentQuantization.unifiedHermite32: * keyFrame.frame = input.ReadByte(); * ushort uH32Value = input.ReadUInt16(); * keyFrame.value = uH32Value & 0xfff; * keyFrame.inSlope = IOUtils.signExtend((uH32Value >> 12) | (input.ReadByte() << 4), 12) / 32f; * keyFrame.outSlope = keyFrame.inSlope; * break; * case RenderBase.OSegmentQuantization.stepLinear64: * keyFrame.frame = input.ReadSingle(); * keyFrame.value = input.ReadSingle(); * break;*/ case 7: // RenderBase.OSegmentQuantization.stepLinear32: uint sL32Value = (uint)input.ReadInt(); keyFrame.Frame = sL32Value & 0xfff; keyFrame.Value = sL32Value >> 12; break; default: Console.WriteLine("Unknown type " + quantization); break; } keyFrame.Frame = (keyFrame.Frame * frameScale) + frameOffset; keyFrame.Value = (keyFrame.Value * valueScale) + valueOffset; group.keys.Add(keyFrame); } }
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 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); }