diff options
Diffstat (limited to 'OpenSim/Region/Framework/Scenes/Animation/BinBVHAnimation.cs')
-rw-r--r-- | OpenSim/Region/Framework/Scenes/Animation/BinBVHAnimation.cs | 646 |
1 files changed, 646 insertions, 0 deletions
diff --git a/OpenSim/Region/Framework/Scenes/Animation/BinBVHAnimation.cs b/OpenSim/Region/Framework/Scenes/Animation/BinBVHAnimation.cs new file mode 100644 index 0000000..b3b38b2 --- /dev/null +++ b/OpenSim/Region/Framework/Scenes/Animation/BinBVHAnimation.cs | |||
@@ -0,0 +1,646 @@ | |||
1 | /* | ||
2 | * Copyright (c) Contributors, http://opensimulator.org/ | ||
3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. | ||
4 | * | ||
5 | * Redistribution and use in source and binary forms, with or without | ||
6 | * modification, are permitted provided that the following conditions are met: | ||
7 | * * Redistributions of source code must retain the above copyright | ||
8 | * notice, this list of conditions and the following disclaimer. | ||
9 | * * Redistributions in binary form must reproduce the above copyright | ||
10 | * notice, this list of conditions and the following disclaimer in the | ||
11 | * documentation and/or other materials provided with the distribution. | ||
12 | * * Neither the name of the OpenSimulator Project nor the | ||
13 | * names of its contributors may be used to endorse or promote products | ||
14 | * derived from this software without specific prior written permission. | ||
15 | * | ||
16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | ||
17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | ||
20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
26 | */ | ||
27 | |||
28 | using System; | ||
29 | using System.IO; | ||
30 | using OpenMetaverse; | ||
31 | |||
32 | namespace OpenSim.Region.Framework.Scenes.Animation | ||
33 | { | ||
34 | /// <summary> | ||
35 | /// Written to decode and encode a binary animation asset. | ||
36 | /// The SecondLife Client reads in a BVH file and converts | ||
37 | /// it to the format described here. This isn't | ||
38 | /// </summary> | ||
39 | public class BinBVHAnimation | ||
40 | { | ||
41 | /// <summary> | ||
42 | /// Rotation Keyframe count (used internally) | ||
43 | /// Don't use this, use the rotationkeys.Length on each joint | ||
44 | /// </summary> | ||
45 | private int rotationkeys; | ||
46 | |||
47 | /// <summary> | ||
48 | /// Position Keyframe count (used internally) | ||
49 | /// Don't use this, use the positionkeys.Length on each joint | ||
50 | /// </summary> | ||
51 | private int positionkeys; | ||
52 | |||
53 | public UInt16 unknown0; // Always 1 | ||
54 | public UInt16 unknown1; // Always 0 | ||
55 | |||
56 | /// <summary> | ||
57 | /// Animation Priority | ||
58 | /// </summary> | ||
59 | public int Priority; | ||
60 | |||
61 | /// <summary> | ||
62 | /// The animation length in seconds. | ||
63 | /// </summary> | ||
64 | public Single Length; | ||
65 | |||
66 | /// <summary> | ||
67 | /// Expression set in the client. Null if [None] is selected | ||
68 | /// </summary> | ||
69 | public string ExpressionName; // "" (null) | ||
70 | |||
71 | /// <summary> | ||
72 | /// The time in seconds to start the animation | ||
73 | /// </summary> | ||
74 | public Single InPoint; | ||
75 | |||
76 | /// <summary> | ||
77 | /// The time in seconds to end the animation | ||
78 | /// </summary> | ||
79 | public Single OutPoint; | ||
80 | |||
81 | /// <summary> | ||
82 | /// Loop the animation | ||
83 | /// </summary> | ||
84 | public bool Loop; | ||
85 | |||
86 | /// <summary> | ||
87 | /// Meta data. Ease in Seconds. | ||
88 | /// </summary> | ||
89 | public Single EaseInTime; | ||
90 | |||
91 | /// <summary> | ||
92 | /// Meta data. Ease out seconds. | ||
93 | /// </summary> | ||
94 | public Single EaseOutTime; | ||
95 | |||
96 | /// <summary> | ||
97 | /// Meta Data for the Hand Pose | ||
98 | /// </summary> | ||
99 | public uint HandPose; | ||
100 | |||
101 | /// <summary> | ||
102 | /// Number of joints defined in the animation | ||
103 | /// Don't use this.. use joints.Length | ||
104 | /// </summary> | ||
105 | private uint m_jointCount; | ||
106 | |||
107 | |||
108 | /// <summary> | ||
109 | /// Contains an array of joints | ||
110 | /// </summary> | ||
111 | public binBVHJoint[] Joints; | ||
112 | |||
113 | |||
114 | public byte[] ToBytes() | ||
115 | { | ||
116 | byte[] outputbytes; | ||
117 | |||
118 | using (MemoryStream ms = new MemoryStream()) | ||
119 | using (BinaryWriter iostream = new BinaryWriter(ms)) | ||
120 | { | ||
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)))); | ||
133 | |||
134 | for (int i = 0; i < Joints.Length; i++) | ||
135 | { | ||
136 | Joints[i].WriteBytesToStream(iostream, InPoint, OutPoint); | ||
137 | } | ||
138 | iostream.Write(BinBVHUtil.ES(Utils.IntToBytes(0))); | ||
139 | |||
140 | using (MemoryStream ms2 = (MemoryStream)iostream.BaseStream) | ||
141 | outputbytes = ms2.ToArray(); | ||
142 | } | ||
143 | |||
144 | return outputbytes; | ||
145 | } | ||
146 | |||
147 | public BinBVHAnimation() | ||
148 | { | ||
149 | rotationkeys = 0; | ||
150 | positionkeys = 0; | ||
151 | unknown0 = 1; | ||
152 | unknown1 = 0; | ||
153 | Priority = 1; | ||
154 | Length = 0; | ||
155 | ExpressionName = string.Empty; | ||
156 | InPoint = 0; | ||
157 | OutPoint = 0; | ||
158 | Loop = false; | ||
159 | EaseInTime = 0; | ||
160 | EaseOutTime = 0; | ||
161 | HandPose = 1; | ||
162 | m_jointCount = 0; | ||
163 | |||
164 | Joints = new binBVHJoint[1]; | ||
165 | Joints[0] = new binBVHJoint(); | ||
166 | Joints[0].Name = "mPelvis"; | ||
167 | Joints[0].Priority = 7; | ||
168 | Joints[0].positionkeys = new binBVHJointKey[1]; | ||
169 | Joints[0].rotationkeys = new binBVHJointKey[1]; | ||
170 | Random rnd = new Random(); | ||
171 | |||
172 | Joints[0].rotationkeys[0] = new binBVHJointKey(); | ||
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); | ||
177 | |||
178 | Joints[0].positionkeys[0] = new binBVHJointKey(); | ||
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); | ||
183 | |||
184 | |||
185 | } | ||
186 | |||
187 | public BinBVHAnimation(byte[] animationdata) | ||
188 | { | ||
189 | int i = 0; | ||
190 | if (!BitConverter.IsLittleEndian) | ||
191 | { | ||
192 | unknown0 = Utils.BytesToUInt16(BinBVHUtil.EndianSwap(animationdata,i,2)); i += 2; // Always 1 | ||
193 | unknown1 = Utils.BytesToUInt16(BinBVHUtil.EndianSwap(animationdata, i, 2)); i += 2; // Always 0 | ||
194 | Priority = Utils.BytesToInt(BinBVHUtil.EndianSwap(animationdata, i, 4)); i += 4; | ||
195 | Length = Utils.BytesToFloat(BinBVHUtil.EndianSwap(animationdata, i, 4), 0); i += 4; | ||
196 | } | ||
197 | else | ||
198 | { | ||
199 | unknown0 = Utils.BytesToUInt16(animationdata, i); i += 2; // Always 1 | ||
200 | unknown1 = Utils.BytesToUInt16(animationdata, i); i += 2; // Always 0 | ||
201 | Priority = Utils.BytesToInt(animationdata, i); i += 4; | ||
202 | Length = Utils.BytesToFloat(animationdata, i); i += 4; | ||
203 | } | ||
204 | ExpressionName = ReadBytesUntilNull(animationdata, ref i); | ||
205 | if (!BitConverter.IsLittleEndian) | ||
206 | { | ||
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; // Handpose? | ||
213 | |||
214 | m_jointCount = Utils.BytesToUInt(animationdata, i); i += 4; // Get Joint count | ||
215 | } | ||
216 | else | ||
217 | { | ||
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; // Handpose? | ||
224 | |||
225 | m_jointCount = Utils.BytesToUInt(animationdata, i); i += 4; // Get Joint count | ||
226 | } | ||
227 | Joints = new binBVHJoint[m_jointCount]; | ||
228 | |||
229 | // deserialize the number of joints in the animation. | ||
230 | // Joints are variable length blocks of binary data consisting of joint data and keyframes | ||
231 | for (int iter = 0; iter < m_jointCount; iter++) | ||
232 | { | ||
233 | binBVHJoint joint = readJoint(animationdata, ref i); | ||
234 | Joints[iter] = joint; | ||
235 | } | ||
236 | } | ||
237 | |||
238 | |||
239 | /// <summary> | ||
240 | /// Variable length strings seem to be null terminated in the animation asset.. but.. | ||
241 | /// use with caution, home grown. | ||
242 | /// advances the index. | ||
243 | /// </summary> | ||
244 | /// <param name="data">The animation asset byte array</param> | ||
245 | /// <param name="i">The offset to start reading</param> | ||
246 | /// <returns>a string</returns> | ||
247 | private static string ReadBytesUntilNull(byte[] data, ref int i) | ||
248 | { | ||
249 | char nterm = '\0'; // Null terminator | ||
250 | int endpos = i; | ||
251 | int startpos = i; | ||
252 | |||
253 | // Find the null character | ||
254 | for (int j = i; j < data.Length; j++) | ||
255 | { | ||
256 | char spot = Convert.ToChar(data[j]); | ||
257 | if (spot == nterm) | ||
258 | { | ||
259 | endpos = j; | ||
260 | break; | ||
261 | } | ||
262 | } | ||
263 | |||
264 | // if we got to the end, then it's a zero length string | ||
265 | if (i == endpos) | ||
266 | { | ||
267 | // advance the 1 null character | ||
268 | i++; | ||
269 | return string.Empty; | ||
270 | } | ||
271 | else | ||
272 | { | ||
273 | // We found the end of the string | ||
274 | // append the bytes from the beginning of the string to the end of the string | ||
275 | // advance i | ||
276 | byte[] interm = new byte[endpos-i]; | ||
277 | for (; i<endpos; i++) | ||
278 | { | ||
279 | interm[i-startpos] = data[i]; | ||
280 | } | ||
281 | i++; // advance past the null character | ||
282 | |||
283 | return Utils.BytesToString(interm); | ||
284 | } | ||
285 | } | ||
286 | |||
287 | /// <summary> | ||
288 | /// Read in a Joint from an animation asset byte array | ||
289 | /// Variable length Joint fields, yay! | ||
290 | /// Advances the index | ||
291 | /// </summary> | ||
292 | /// <param name="data">animation asset byte array</param> | ||
293 | /// <param name="i">Byte Offset of the start of the joint</param> | ||
294 | /// <returns>The Joint data serialized into the binBVHJoint structure</returns> | ||
295 | private binBVHJoint readJoint(byte[] data, ref int i) | ||
296 | { | ||
297 | |||
298 | binBVHJointKey[] positions; | ||
299 | binBVHJointKey[] rotations; | ||
300 | |||
301 | binBVHJoint pJoint = new binBVHJoint(); | ||
302 | |||
303 | /* | ||
304 | 109 | ||
305 | 84 | ||
306 | 111 | ||
307 | 114 | ||
308 | 114 | ||
309 | 111 | ||
310 | 0 <--- Null terminator | ||
311 | */ | ||
312 | |||
313 | pJoint.Name = ReadBytesUntilNull(data, ref i); // Joint name | ||
314 | |||
315 | /* | ||
316 | 2 <- Priority Revisited | ||
317 | 0 | ||
318 | 0 | ||
319 | 0 | ||
320 | */ | ||
321 | |||
322 | /* | ||
323 | 5 <-- 5 keyframes | ||
324 | 0 | ||
325 | 0 | ||
326 | 0 | ||
327 | ... 5 Keyframe data blocks | ||
328 | */ | ||
329 | |||
330 | /* | ||
331 | 2 <-- 2 keyframes | ||
332 | 0 | ||
333 | 0 | ||
334 | 0 | ||
335 | .. 2 Keyframe data blocks | ||
336 | */ | ||
337 | if (!BitConverter.IsLittleEndian) | ||
338 | { | ||
339 | pJoint.Priority = Utils.BytesToInt(BinBVHUtil.EndianSwap(data, i, 4)); i += 4; // Joint Priority override? | ||
340 | rotationkeys = Utils.BytesToInt(BinBVHUtil.EndianSwap(data, i, 4)); i += 4; // How many rotation keyframes | ||
341 | } | ||
342 | else | ||
343 | { | ||
344 | pJoint.Priority = Utils.BytesToInt(data, i); i += 4; // Joint Priority override? | ||
345 | rotationkeys = Utils.BytesToInt(data, i); i += 4; // How many rotation keyframes | ||
346 | } | ||
347 | |||
348 | // argh! floats into two bytes!.. bad bad bad bad | ||
349 | // After fighting with it for a while.. -1, to 1 seems to give the best results | ||
350 | rotations = readKeys(data, ref i, rotationkeys, -1f, 1f); | ||
351 | for (int iter = 0; iter < rotations.Length; iter++) | ||
352 | { | ||
353 | rotations[iter].W = 1f - | ||
354 | (rotations[iter].key_element.X + rotations[iter].key_element.Y + | ||
355 | rotations[iter].key_element.Z); | ||
356 | } | ||
357 | |||
358 | |||
359 | if (!BitConverter.IsLittleEndian) | ||
360 | { | ||
361 | positionkeys = Utils.BytesToInt(BinBVHUtil.EndianSwap(data, i, 4)); i += 4; // How many position keyframes | ||
362 | } | ||
363 | else | ||
364 | { | ||
365 | positionkeys = Utils.BytesToInt(data, i); i += 4; // How many position keyframes | ||
366 | } | ||
367 | |||
368 | // Read in position keyframes | ||
369 | // argh! more floats into two bytes!.. *head desk* | ||
370 | // After fighting with it for a while.. -5, to 5 seems to give the best results | ||
371 | positions = readKeys(data, ref i, positionkeys, -5f, 5f); | ||
372 | |||
373 | pJoint.rotationkeys = rotations; | ||
374 | pJoint.positionkeys = positions; | ||
375 | |||
376 | return pJoint; | ||
377 | } | ||
378 | |||
379 | /// <summary> | ||
380 | /// Read Keyframes of a certain type | ||
381 | /// advance i | ||
382 | /// </summary> | ||
383 | /// <param name="data">Animation Byte array</param> | ||
384 | /// <param name="i">Offset in the Byte Array. Will be advanced</param> | ||
385 | /// <param name="keycount">Number of Keyframes</param> | ||
386 | /// <param name="min">Scaling Min to pass to the Uint16ToFloat method</param> | ||
387 | /// <param name="max">Scaling Max to pass to the Uint16ToFloat method</param> | ||
388 | /// <returns></returns> | ||
389 | private binBVHJointKey[] readKeys(byte[] data, ref int i, int keycount, float min, float max) | ||
390 | { | ||
391 | float x; | ||
392 | float y; | ||
393 | float z; | ||
394 | |||
395 | /* | ||
396 | 0.o, Float values in Two bytes.. this is just wrong >:( | ||
397 | 17 255 <-- Time Code | ||
398 | 17 255 <-- Time Code | ||
399 | 255 255 <-- X | ||
400 | 127 127 <-- X | ||
401 | 255 255 <-- Y | ||
402 | 127 127 <-- Y | ||
403 | 213 213 <-- Z | ||
404 | 142 142 <---Z | ||
405 | |||
406 | */ | ||
407 | |||
408 | binBVHJointKey[] m_keys = new binBVHJointKey[keycount]; | ||
409 | for (int j = 0; j < keycount; j++) | ||
410 | { | ||
411 | binBVHJointKey pJKey = new binBVHJointKey(); | ||
412 | if (!BitConverter.IsLittleEndian) | ||
413 | { | ||
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; | ||
418 | } | ||
419 | else | ||
420 | { | ||
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; | ||
425 | } | ||
426 | pJKey.key_element = new Vector3(x, y, z); | ||
427 | m_keys[j] = pJKey; | ||
428 | } | ||
429 | return m_keys; | ||
430 | } | ||
431 | |||
432 | |||
433 | |||
434 | } | ||
435 | /// <summary> | ||
436 | /// A Joint and it's associated meta data and keyframes | ||
437 | /// </summary> | ||
438 | public struct binBVHJoint | ||
439 | { | ||
440 | /// <summary> | ||
441 | /// Name of the Joint. Matches the avatar_skeleton.xml in client distros | ||
442 | /// </summary> | ||
443 | public string Name; | ||
444 | |||
445 | /// <summary> | ||
446 | /// Joint Animation Override? Was the same as the Priority in testing.. | ||
447 | /// </summary> | ||
448 | public int Priority; | ||
449 | |||
450 | /// <summary> | ||
451 | /// Array of Rotation Keyframes in order from earliest to latest | ||
452 | /// </summary> | ||
453 | public binBVHJointKey[] rotationkeys; | ||
454 | |||
455 | /// <summary> | ||
456 | /// Array of Position Keyframes in order from earliest to latest | ||
457 | /// This seems to only be for the Pelvis? | ||
458 | /// </summary> | ||
459 | public binBVHJointKey[] positionkeys; | ||
460 | |||
461 | |||
462 | |||
463 | public void WriteBytesToStream(BinaryWriter iostream, float InPoint, float OutPoint) | ||
464 | { | ||
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++) | ||
469 | { | ||
470 | rotationkeys[i].WriteBytesToStream(iostream, InPoint, OutPoint, -1f, 1f); | ||
471 | } | ||
472 | iostream.Write(BinBVHUtil.ES(Utils.IntToBytes((positionkeys.Length)))); | ||
473 | for (int i = 0; i < positionkeys.Length; i++) | ||
474 | { | ||
475 | positionkeys[i].WriteBytesToStream(iostream, InPoint, OutPoint, -256f, 256f); | ||
476 | } | ||
477 | } | ||
478 | } | ||
479 | |||
480 | /// <summary> | ||
481 | /// A Joint Keyframe. This is either a position or a rotation. | ||
482 | /// </summary> | ||
483 | public struct binBVHJointKey | ||
484 | { | ||
485 | // Time in seconds for this keyframe. | ||
486 | public float time; | ||
487 | |||
488 | /// <summary> | ||
489 | /// Either a Vector3 position or a Vector3 Euler rotation | ||
490 | /// </summary> | ||
491 | public Vector3 key_element; | ||
492 | |||
493 | public float W; | ||
494 | |||
495 | public void WriteBytesToStream(BinaryWriter iostream, float InPoint, float OutPoint, float min, float max) | ||
496 | { | ||
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)))); | ||
501 | } | ||
502 | } | ||
503 | |||
504 | /// <summary> | ||
505 | /// Poses set in the animation metadata for the hands. | ||
506 | /// </summary> | ||
507 | public enum HandPose : uint | ||
508 | { | ||
509 | Spread = 0, | ||
510 | Relaxed = 1, | ||
511 | Point_Both = 2, | ||
512 | Fist = 3, | ||
513 | Relaxed_Left = 4, | ||
514 | Point_Left = 5, | ||
515 | Fist_Left = 6, | ||
516 | Relaxed_Right = 7, | ||
517 | Point_Right = 8, | ||
518 | Fist_Right = 9, | ||
519 | Salute_Right = 10, | ||
520 | Typing = 11, | ||
521 | Peace_Right = 12 | ||
522 | } | ||
523 | public static class BinBVHUtil | ||
524 | { | ||
525 | public const float ONE_OVER_U16_MAX = 1.0f / UInt16.MaxValue; | ||
526 | |||
527 | public static UInt16 FloatToUInt16(float val, float lower, float upper) | ||
528 | { | ||
529 | UInt16 uival = 0; | ||
530 | //m_parentGroup.GetTimeDilation() * (float)ushort.MaxValue | ||
531 | //0-1 | ||
532 | |||
533 | // float difference = upper - lower; | ||
534 | // we're trying to get a zero lower and modify all values equally so we get a percentage position | ||
535 | if (lower > 0) | ||
536 | { | ||
537 | upper -= lower; | ||
538 | val = val - lower; | ||
539 | |||
540 | // start with 500 upper and 200 lower.. subtract 200 from the upper and the value | ||
541 | } | ||
542 | else //if (lower < 0 && upper > 0) | ||
543 | { | ||
544 | // double negative, 0 minus negative 5 is 5. | ||
545 | upper += 0 - lower; | ||
546 | lower += 0 - lower; | ||
547 | val += 0 - lower; | ||
548 | } | ||
549 | |||
550 | if (upper == 0) | ||
551 | val = 0; | ||
552 | else | ||
553 | { | ||
554 | val /= upper; | ||
555 | } | ||
556 | |||
557 | uival = (UInt16)(val * UInt16.MaxValue); | ||
558 | |||
559 | return uival; | ||
560 | } | ||
561 | |||
562 | |||
563 | /// <summary> | ||
564 | /// Endian Swap | ||
565 | /// Swaps endianness if necessary | ||
566 | /// </summary> | ||
567 | /// <param name="arr">Input array</param> | ||
568 | /// <returns></returns> | ||
569 | public static byte[] ES(byte[] arr) | ||
570 | { | ||
571 | if (!BitConverter.IsLittleEndian) | ||
572 | Array.Reverse(arr); | ||
573 | return arr; | ||
574 | } | ||
575 | public static byte[] EndianSwap(byte[] arr, int offset, int len) | ||
576 | { | ||
577 | byte[] bendian = new byte[offset + len]; | ||
578 | Buffer.BlockCopy(arr, offset, bendian, 0, len); | ||
579 | Array.Reverse(bendian); | ||
580 | return bendian; | ||
581 | } | ||
582 | |||
583 | public static byte[] WriteNullTerminatedString(string str) | ||
584 | { | ||
585 | byte[] output = new byte[str.Length + 1]; | ||
586 | Char[] chr = str.ToCharArray(); | ||
587 | int i = 0; | ||
588 | for (i = 0; i < chr.Length; i++) | ||
589 | { | ||
590 | output[i] = Convert.ToByte(chr[i]); | ||
591 | |||
592 | } | ||
593 | |||
594 | output[i] = Convert.ToByte('\0'); | ||
595 | return output; | ||
596 | } | ||
597 | |||
598 | } | ||
599 | } | ||
600 | /* | ||
601 | switch (jointname) | ||
602 | { | ||
603 | case "mPelvis": | ||
604 | case "mTorso": | ||
605 | case "mNeck": | ||
606 | case "mHead": | ||
607 | case "mChest": | ||
608 | case "mHipLeft": | ||
609 | case "mHipRight": | ||
610 | case "mKneeLeft": | ||
611 | case "mKneeRight": | ||
612 | // XYZ->ZXY | ||
613 | t = x; | ||
614 | x = y; | ||
615 | y = t; | ||
616 | break; | ||
617 | case "mCollarLeft": | ||
618 | case "mCollarRight": | ||
619 | case "mElbowLeft": | ||
620 | case "mElbowRight": | ||
621 | // YZX ->ZXY | ||
622 | t = z; | ||
623 | z = x; | ||
624 | x = y; | ||
625 | y = t; | ||
626 | break; | ||
627 | case "mWristLeft": | ||
628 | case "mWristRight": | ||
629 | case "mShoulderLeft": | ||
630 | case "mShoulderRight": | ||
631 | // ZYX->ZXY | ||
632 | t = y; | ||
633 | y = z; | ||
634 | z = t; | ||
635 | |||
636 | break; | ||
637 | case "mAnkleLeft": | ||
638 | case "mAnkleRight": | ||
639 | // XYZ ->ZXY | ||
640 | t = x; | ||
641 | x = z; | ||
642 | z = y; | ||
643 | y = t; | ||
644 | break; | ||
645 | } | ||
646 | */ \ No newline at end of file | ||