45 private int rotationkeys;
51 private int positionkeys;
105 private uint m_jointCount;
118 using (MemoryStream ms =
new MemoryStream())
119 using (BinaryWriter iostream =
new BinaryWriter(ms))
121 iostream.Write(BinBVHUtil.ES(Utils.UInt16ToBytes(unknown0)));
122 iostream.Write(BinBVHUtil.ES(Utils.UInt16ToBytes(unknown1)));
123 iostream.Write(BinBVHUtil.ES(Utils.IntToBytes(Priority)));
124 iostream.Write(BinBVHUtil.ES(Utils.FloatToBytes(Length)));
125 iostream.Write(BinBVHUtil.WriteNullTerminatedString(ExpressionName));
126 iostream.Write(BinBVHUtil.ES(Utils.FloatToBytes(InPoint)));
127 iostream.Write(BinBVHUtil.ES(Utils.FloatToBytes(OutPoint)));
128 iostream.Write(BinBVHUtil.ES(Utils.IntToBytes(Loop ? 1 : 0)));
129 iostream.Write(BinBVHUtil.ES(Utils.FloatToBytes(EaseInTime)));
130 iostream.Write(BinBVHUtil.ES(Utils.FloatToBytes(EaseOutTime)));
131 iostream.Write(BinBVHUtil.ES(Utils.UIntToBytes(
HandPose)));
132 iostream.Write(BinBVHUtil.ES(Utils.UIntToBytes((uint)(Joints.Length))));
134 for (
int i = 0; i < Joints.Length; i++)
136 Joints[i].WriteBytesToStream(iostream, InPoint, OutPoint);
138 iostream.Write(BinBVHUtil.ES(Utils.IntToBytes(0)));
140 using (MemoryStream ms2 = (MemoryStream)iostream.BaseStream)
141 outputbytes = ms2.ToArray();
155 ExpressionName = string.Empty;
166 Joints[0].Name =
"mPelvis";
167 Joints[0].Priority = 7;
170 Random rnd =
new Random();
173 Joints[0].rotationkeys[0].time = (0f);
174 Joints[0].rotationkeys[0].key_element.X = ((float)rnd.NextDouble() * 2 - 1);
175 Joints[0].rotationkeys[0].key_element.Y = ((float)rnd.NextDouble() * 2 - 1);
176 Joints[0].rotationkeys[0].key_element.Z = ((float)rnd.NextDouble() * 2 - 1);
179 Joints[0].positionkeys[0].time = (0f);
180 Joints[0].positionkeys[0].key_element.X = ((float)rnd.NextDouble() * 2 - 1);
181 Joints[0].positionkeys[0].key_element.Y = ((float)rnd.NextDouble() * 2 - 1);
182 Joints[0].positionkeys[0].key_element.Z = ((float)rnd.NextDouble() * 2 - 1);
190 if (!BitConverter.IsLittleEndian)
192 unknown0 = Utils.BytesToUInt16(BinBVHUtil.EndianSwap(animationdata,i,2)); i += 2;
193 unknown1 = Utils.BytesToUInt16(BinBVHUtil.EndianSwap(animationdata, i, 2)); i += 2;
194 Priority = Utils.BytesToInt(BinBVHUtil.EndianSwap(animationdata, i, 4)); i += 4;
195 Length = Utils.BytesToFloat(BinBVHUtil.EndianSwap(animationdata, i, 4), 0); i += 4;
199 unknown0 = Utils.BytesToUInt16(animationdata, i); i += 2;
200 unknown1 = Utils.BytesToUInt16(animationdata, i); i += 2;
201 Priority = Utils.BytesToInt(animationdata, i); i += 4;
202 Length = Utils.BytesToFloat(animationdata, i); i += 4;
204 ExpressionName = ReadBytesUntilNull(animationdata, ref i);
205 if (!BitConverter.IsLittleEndian)
207 InPoint = Utils.BytesToFloat(BinBVHUtil.EndianSwap(animationdata, i, 4), 0); i += 4;
208 OutPoint = Utils.BytesToFloat(BinBVHUtil.EndianSwap(animationdata, i, 4), 0); i += 4;
209 Loop = (Utils.BytesToInt(BinBVHUtil.EndianSwap(animationdata, i, 4)) != 0); i += 4;
210 EaseInTime = Utils.BytesToFloat(BinBVHUtil.EndianSwap(animationdata, i, 4), 0); i += 4;
211 EaseOutTime = Utils.BytesToFloat(BinBVHUtil.EndianSwap(animationdata, i, 4), 0); i += 4;
212 HandPose = Utils.BytesToUInt(BinBVHUtil.EndianSwap(animationdata, i, 4)); i += 4;
214 m_jointCount = Utils.BytesToUInt(animationdata, i); i += 4;
218 InPoint = Utils.BytesToFloat(animationdata, i); i += 4;
219 OutPoint = Utils.BytesToFloat(animationdata, i); i += 4;
220 Loop = (Utils.BytesToInt(animationdata, i) != 0); i += 4;
221 EaseInTime = Utils.BytesToFloat(animationdata, i); i += 4;
222 EaseOutTime = Utils.BytesToFloat(animationdata, i); i += 4;
223 HandPose = Utils.BytesToUInt(animationdata, i); i += 4;
225 m_jointCount = Utils.BytesToUInt(animationdata, i); i += 4;
231 for (
int iter = 0; iter < m_jointCount; iter++)
233 binBVHJoint joint = readJoint(animationdata, ref i);
234 Joints[iter] = joint;
247 private static string ReadBytesUntilNull(byte[] data, ref
int i)
254 for (
int j = i; j < data.Length; j++)
256 char spot = Convert.ToChar(data[j]);
276 byte[] interm =
new byte[endpos-i];
277 for (; i<endpos; i++)
279 interm[i-startpos] = data[i];
283 return Utils.BytesToString(interm);
295 private binBVHJoint readJoint(byte[] data, ref
int i)
298 binBVHJointKey[] positions;
299 binBVHJointKey[] rotations;
301 binBVHJoint pJoint =
new binBVHJoint();
313 pJoint.Name = ReadBytesUntilNull(data, ref i);
337 if (!BitConverter.IsLittleEndian)
339 pJoint.Priority = Utils.BytesToInt(BinBVHUtil.EndianSwap(data, i, 4)); i += 4;
340 rotationkeys = Utils.BytesToInt(BinBVHUtil.EndianSwap(data, i, 4)); i += 4;
344 pJoint.Priority = Utils.BytesToInt(data, i); i += 4;
345 rotationkeys = Utils.BytesToInt(data, i); i += 4;
350 rotations = readKeys(data, ref i, rotationkeys, -1f, 1f);
351 for (
int iter = 0; iter < rotations.Length; iter++)
353 rotations[iter].W = 1f -
354 (rotations[iter].key_element.X + rotations[iter].key_element.Y +
355 rotations[iter].key_element.Z);
359 if (!BitConverter.IsLittleEndian)
361 positionkeys = Utils.BytesToInt(BinBVHUtil.EndianSwap(data, i, 4)); i += 4;
365 positionkeys = Utils.BytesToInt(data, i); i += 4;
371 positions = readKeys(data, ref i, positionkeys, -5f, 5f);
373 pJoint.rotationkeys = rotations;
374 pJoint.positionkeys = positions;
389 private binBVHJointKey[] readKeys(byte[] data, ref
int i,
int keycount,
float min,
float max)
408 binBVHJointKey[] m_keys =
new binBVHJointKey[keycount];
409 for (
int j = 0; j < keycount; j++)
411 binBVHJointKey pJKey =
new binBVHJointKey();
412 if (!BitConverter.IsLittleEndian)
414 pJKey.time = Utils.UInt16ToFloat(BinBVHUtil.EndianSwap(data, i, 2), 0, InPoint, OutPoint); i += 2;
415 x = Utils.UInt16ToFloat(BinBVHUtil.EndianSwap(data, i, 2), 0, min, max); i += 2;
416 y = Utils.UInt16ToFloat(BinBVHUtil.EndianSwap(data, i, 2), 0, min, max); i += 2;
417 z = Utils.UInt16ToFloat(BinBVHUtil.EndianSwap(data, i, 2), 0, min, max); i += 2;
421 pJKey.time = Utils.UInt16ToFloat(data, i, InPoint, OutPoint); i += 2;
422 x = Utils.UInt16ToFloat(data, i, min, max); i += 2;
423 y = Utils.UInt16ToFloat(data, i, min, max); i += 2;
424 z = Utils.UInt16ToFloat(data, i, min, max); i += 2;
426 pJKey.key_element =
new Vector3(x, y, z);
465 iostream.Write(BinBVHUtil.WriteNullTerminatedString(Name));
466 iostream.Write(BinBVHUtil.ES(Utils.IntToBytes(Priority)));
467 iostream.Write(BinBVHUtil.ES(Utils.IntToBytes(rotationkeys.Length)));
468 for (
int i=0;i<rotationkeys.Length;i++)
470 rotationkeys[i].WriteBytesToStream(iostream, InPoint, OutPoint, -1f, 1f);
472 iostream.Write(BinBVHUtil.ES(Utils.IntToBytes((positionkeys.Length))));
473 for (
int i = 0; i < positionkeys.Length; i++)
475 positionkeys[i].WriteBytesToStream(iostream, InPoint, OutPoint, -256f, 256f);
495 public void WriteBytesToStream(BinaryWriter iostream,
float InPoint,
float OutPoint,
float min,
float max)
497 iostream.Write(BinBVHUtil.ES(Utils.UInt16ToBytes(BinBVHUtil.FloatToUInt16(time, InPoint, OutPoint))));
498 iostream.Write(BinBVHUtil.ES(Utils.UInt16ToBytes(BinBVHUtil.FloatToUInt16(key_element.X, min, max))));
499 iostream.Write(BinBVHUtil.ES(Utils.UInt16ToBytes(BinBVHUtil.FloatToUInt16(key_element.Y, min, max))));
500 iostream.Write(BinBVHUtil.ES(Utils.UInt16ToBytes(BinBVHUtil.FloatToUInt16(key_element.Z, min, max))));
523 public static class BinBVHUtil
525 public const float ONE_OVER_U16_MAX = 1.0f / UInt16.MaxValue;
527 public static UInt16 FloatToUInt16(
float val,
float lower,
float upper)
557 uival = (UInt16)(val * UInt16.MaxValue);
569 public static byte[] ES(byte[] arr)
571 if (!BitConverter.IsLittleEndian)
575 public static byte[] EndianSwap(byte[] arr,
int offset,
int len)
577 byte[] bendian =
new byte[offset + len];
578 Buffer.BlockCopy(arr, offset, bendian, 0, len);
579 Array.Reverse(bendian);
583 public static byte[] WriteNullTerminatedString(
string str)
585 byte[] output =
new byte[str.Length + 1];
586 Char[] chr = str.ToCharArray();
588 for (i = 0; i < chr.Length; i++)
590 output[i] = Convert.ToByte(chr[i]);
594 output[i] = Convert.ToByte(
'\0');
int Priority
Joint Animation Override? Was the same as the Priority in testing..
binBVHJoint[] Joints
Contains an array of joints
uint HandPose
Meta Data for the Hand Pose
Single OutPoint
The time in seconds to end the animation
binBVHJointKey[] positionkeys
Array of Position Keyframes in order from earliest to latest This seems to only be for the Pelvis...
void WriteBytesToStream(BinaryWriter iostream, float InPoint, float OutPoint)
int Priority
Animation Priority
Single InPoint
The time in seconds to start the animation
Single EaseOutTime
Meta data. Ease out seconds.
Vector3 key_element
Either a Vector3 position or a Vector3 Euler rotation
Single EaseInTime
Meta data. Ease in Seconds.
HandPose
Poses set in the animation metadata for the hands.
Written to decode and encode a binary animation asset. The SecondLife Client reads in a BVH file and ...
A Joint and it's associated meta data and keyframes
BinBVHAnimation(byte[] animationdata)
string ExpressionName
Expression set in the client. Null if [None] is selected
OpenSim.Framework.Animation Animation
bool Loop
Loop the animation
void WriteBytesToStream(BinaryWriter iostream, float InPoint, float OutPoint, float min, float max)
string Name
Name of the Joint. Matches the avatar_skeleton.xml in client distros
A Joint Keyframe. This is either a position or a rotation.
binBVHJointKey[] rotationkeys
Array of Rotation Keyframes in order from earliest to latest
Single Length
The animation length in seconds.