diff options
author | Justin Clark-Casey (justincc) | 2009-11-17 16:25:52 +0000 |
---|---|---|
committer | Justin Clark-Casey (justincc) | 2009-11-17 16:25:52 +0000 |
commit | da255be05a451ba9a48efd6f167849228a54273b (patch) | |
tree | 51ac540e825d14dffc8426313c21304f0e9bd163 /OpenSim/Region/Framework/Scenes/Animation/BinBVHAnimation.cs | |
parent | minor: remove mono compiler warning due to unreachable code in GroupsModule (diff) | |
download | opensim-SC-da255be05a451ba9a48efd6f167849228a54273b.zip opensim-SC-da255be05a451ba9a48efd6f167849228a54273b.tar.gz opensim-SC-da255be05a451ba9a48efd6f167849228a54273b.tar.bz2 opensim-SC-da255be05a451ba9a48efd6f167849228a54273b.tar.xz |
refactor: move AvatarAnimations, BinBVHAnimation
Diffstat (limited to 'OpenSim/Region/Framework/Scenes/Animation/BinBVHAnimation.cs')
-rw-r--r-- | OpenSim/Region/Framework/Scenes/Animation/BinBVHAnimation.cs | 643 |
1 files changed, 643 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..3afc87f --- /dev/null +++ b/OpenSim/Region/Framework/Scenes/Animation/BinBVHAnimation.cs | |||
@@ -0,0 +1,643 @@ | |||
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 = new byte[0]; | ||
117 | |||
118 | BinaryWriter iostream = new BinaryWriter(new MemoryStream()); | ||
119 | iostream.Write(BinBVHUtil.ES(Utils.UInt16ToBytes(unknown0))); | ||
120 | iostream.Write(BinBVHUtil.ES(Utils.UInt16ToBytes(unknown1))); | ||
121 | iostream.Write(BinBVHUtil.ES(Utils.IntToBytes(Priority))); | ||
122 | iostream.Write(BinBVHUtil.ES(Utils.FloatToBytes(Length))); | ||
123 | iostream.Write(BinBVHUtil.WriteNullTerminatedString(ExpressionName)); | ||
124 | iostream.Write(BinBVHUtil.ES(Utils.FloatToBytes(InPoint))); | ||
125 | iostream.Write(BinBVHUtil.ES(Utils.FloatToBytes(OutPoint))); | ||
126 | iostream.Write(BinBVHUtil.ES(Utils.IntToBytes(Loop ? 1 : 0))); | ||
127 | iostream.Write(BinBVHUtil.ES(Utils.FloatToBytes(EaseInTime))); | ||
128 | iostream.Write(BinBVHUtil.ES(Utils.FloatToBytes(EaseOutTime))); | ||
129 | iostream.Write(BinBVHUtil.ES(Utils.UIntToBytes(HandPose))); | ||
130 | iostream.Write(BinBVHUtil.ES(Utils.UIntToBytes((uint)(Joints.Length)))); | ||
131 | |||
132 | for (int i = 0; i < Joints.Length; i++) | ||
133 | { | ||
134 | Joints[i].WriteBytesToStream(iostream, InPoint, OutPoint); | ||
135 | } | ||
136 | iostream.Write(BinBVHUtil.ES(Utils.IntToBytes(0))); | ||
137 | MemoryStream ms = (MemoryStream)iostream.BaseStream; | ||
138 | outputbytes = ms.ToArray(); | ||
139 | ms.Close(); | ||
140 | iostream.Close(); | ||
141 | return outputbytes; | ||
142 | } | ||
143 | |||
144 | public BinBVHAnimation() | ||
145 | { | ||
146 | rotationkeys = 0; | ||
147 | positionkeys = 0; | ||
148 | unknown0 = 1; | ||
149 | unknown1 = 0; | ||
150 | Priority = 1; | ||
151 | Length = 0; | ||
152 | ExpressionName = string.Empty; | ||
153 | InPoint = 0; | ||
154 | OutPoint = 0; | ||
155 | Loop = false; | ||
156 | EaseInTime = 0; | ||
157 | EaseOutTime = 0; | ||
158 | HandPose = 1; | ||
159 | m_jointCount = 0; | ||
160 | |||
161 | Joints = new binBVHJoint[1]; | ||
162 | Joints[0] = new binBVHJoint(); | ||
163 | Joints[0].Name = "mPelvis"; | ||
164 | Joints[0].Priority = 7; | ||
165 | Joints[0].positionkeys = new binBVHJointKey[1]; | ||
166 | Joints[0].rotationkeys = new binBVHJointKey[1]; | ||
167 | Random rnd = new Random(); | ||
168 | |||
169 | Joints[0].rotationkeys[0] = new binBVHJointKey(); | ||
170 | Joints[0].rotationkeys[0].time = (0f); | ||
171 | Joints[0].rotationkeys[0].key_element.X = ((float)rnd.NextDouble() * 2 - 1); | ||
172 | Joints[0].rotationkeys[0].key_element.Y = ((float)rnd.NextDouble() * 2 - 1); | ||
173 | Joints[0].rotationkeys[0].key_element.Z = ((float)rnd.NextDouble() * 2 - 1); | ||
174 | |||
175 | Joints[0].positionkeys[0] = new binBVHJointKey(); | ||
176 | Joints[0].positionkeys[0].time = (0f); | ||
177 | Joints[0].positionkeys[0].key_element.X = ((float)rnd.NextDouble() * 2 - 1); | ||
178 | Joints[0].positionkeys[0].key_element.Y = ((float)rnd.NextDouble() * 2 - 1); | ||
179 | Joints[0].positionkeys[0].key_element.Z = ((float)rnd.NextDouble() * 2 - 1); | ||
180 | |||
181 | |||
182 | } | ||
183 | |||
184 | public BinBVHAnimation(byte[] animationdata) | ||
185 | { | ||
186 | int i = 0; | ||
187 | if (!BitConverter.IsLittleEndian) | ||
188 | { | ||
189 | unknown0 = Utils.BytesToUInt16(BinBVHUtil.EndianSwap(animationdata,i,2)); i += 2; // Always 1 | ||
190 | unknown1 = Utils.BytesToUInt16(BinBVHUtil.EndianSwap(animationdata, i, 2)); i += 2; // Always 0 | ||
191 | Priority = Utils.BytesToInt(BinBVHUtil.EndianSwap(animationdata, i, 4)); i += 4; | ||
192 | Length = Utils.BytesToFloat(BinBVHUtil.EndianSwap(animationdata, i, 4), 0); i += 4; | ||
193 | } | ||
194 | else | ||
195 | { | ||
196 | unknown0 = Utils.BytesToUInt16(animationdata, i); i += 2; // Always 1 | ||
197 | unknown1 = Utils.BytesToUInt16(animationdata, i); i += 2; // Always 0 | ||
198 | Priority = Utils.BytesToInt(animationdata, i); i += 4; | ||
199 | Length = Utils.BytesToFloat(animationdata, i); i += 4; | ||
200 | } | ||
201 | ExpressionName = ReadBytesUntilNull(animationdata, ref i); | ||
202 | if (!BitConverter.IsLittleEndian) | ||
203 | { | ||
204 | InPoint = Utils.BytesToFloat(BinBVHUtil.EndianSwap(animationdata, i, 4), 0); i += 4; | ||
205 | OutPoint = Utils.BytesToFloat(BinBVHUtil.EndianSwap(animationdata, i, 4), 0); i += 4; | ||
206 | Loop = (Utils.BytesToInt(BinBVHUtil.EndianSwap(animationdata, i, 4)) != 0); i += 4; | ||
207 | EaseInTime = Utils.BytesToFloat(BinBVHUtil.EndianSwap(animationdata, i, 4), 0); i += 4; | ||
208 | EaseOutTime = Utils.BytesToFloat(BinBVHUtil.EndianSwap(animationdata, i, 4), 0); i += 4; | ||
209 | HandPose = Utils.BytesToUInt(BinBVHUtil.EndianSwap(animationdata, i, 4)); i += 4; // Handpose? | ||
210 | |||
211 | m_jointCount = Utils.BytesToUInt(animationdata, i); i += 4; // Get Joint count | ||
212 | } | ||
213 | else | ||
214 | { | ||
215 | InPoint = Utils.BytesToFloat(animationdata, i); i += 4; | ||
216 | OutPoint = Utils.BytesToFloat(animationdata, i); i += 4; | ||
217 | Loop = (Utils.BytesToInt(animationdata, i) != 0); i += 4; | ||
218 | EaseInTime = Utils.BytesToFloat(animationdata, i); i += 4; | ||
219 | EaseOutTime = Utils.BytesToFloat(animationdata, i); i += 4; | ||
220 | HandPose = Utils.BytesToUInt(animationdata, i); i += 4; // Handpose? | ||
221 | |||
222 | m_jointCount = Utils.BytesToUInt(animationdata, i); i += 4; // Get Joint count | ||
223 | } | ||
224 | Joints = new binBVHJoint[m_jointCount]; | ||
225 | |||
226 | // deserialize the number of joints in the animation. | ||
227 | // Joints are variable length blocks of binary data consisting of joint data and keyframes | ||
228 | for (int iter = 0; iter < m_jointCount; iter++) | ||
229 | { | ||
230 | binBVHJoint joint = readJoint(animationdata, ref i); | ||
231 | Joints[iter] = joint; | ||
232 | } | ||
233 | } | ||
234 | |||
235 | |||
236 | /// <summary> | ||
237 | /// Variable length strings seem to be null terminated in the animation asset.. but.. | ||
238 | /// use with caution, home grown. | ||
239 | /// advances the index. | ||
240 | /// </summary> | ||
241 | /// <param name="data">The animation asset byte array</param> | ||
242 | /// <param name="i">The offset to start reading</param> | ||
243 | /// <returns>a string</returns> | ||
244 | private static string ReadBytesUntilNull(byte[] data, ref int i) | ||
245 | { | ||
246 | char nterm = '\0'; // Null terminator | ||
247 | int endpos = i; | ||
248 | int startpos = i; | ||
249 | |||
250 | // Find the null character | ||
251 | for (int j = i; j < data.Length; j++) | ||
252 | { | ||
253 | char spot = Convert.ToChar(data[j]); | ||
254 | if (spot == nterm) | ||
255 | { | ||
256 | endpos = j; | ||
257 | break; | ||
258 | } | ||
259 | } | ||
260 | |||
261 | // if we got to the end, then it's a zero length string | ||
262 | if (i == endpos) | ||
263 | { | ||
264 | // advance the 1 null character | ||
265 | i++; | ||
266 | return string.Empty; | ||
267 | } | ||
268 | else | ||
269 | { | ||
270 | // We found the end of the string | ||
271 | // append the bytes from the beginning of the string to the end of the string | ||
272 | // advance i | ||
273 | byte[] interm = new byte[endpos-i]; | ||
274 | for (; i<endpos; i++) | ||
275 | { | ||
276 | interm[i-startpos] = data[i]; | ||
277 | } | ||
278 | i++; // advance past the null character | ||
279 | |||
280 | return Utils.BytesToString(interm); | ||
281 | } | ||
282 | } | ||
283 | |||
284 | /// <summary> | ||
285 | /// Read in a Joint from an animation asset byte array | ||
286 | /// Variable length Joint fields, yay! | ||
287 | /// Advances the index | ||
288 | /// </summary> | ||
289 | /// <param name="data">animation asset byte array</param> | ||
290 | /// <param name="i">Byte Offset of the start of the joint</param> | ||
291 | /// <returns>The Joint data serialized into the binBVHJoint structure</returns> | ||
292 | private binBVHJoint readJoint(byte[] data, ref int i) | ||
293 | { | ||
294 | |||
295 | binBVHJointKey[] positions; | ||
296 | binBVHJointKey[] rotations; | ||
297 | |||
298 | binBVHJoint pJoint = new binBVHJoint(); | ||
299 | |||
300 | /* | ||
301 | 109 | ||
302 | 84 | ||
303 | 111 | ||
304 | 114 | ||
305 | 114 | ||
306 | 111 | ||
307 | 0 <--- Null terminator | ||
308 | */ | ||
309 | |||
310 | pJoint.Name = ReadBytesUntilNull(data, ref i); // Joint name | ||
311 | |||
312 | /* | ||
313 | 2 <- Priority Revisited | ||
314 | 0 | ||
315 | 0 | ||
316 | 0 | ||
317 | */ | ||
318 | |||
319 | /* | ||
320 | 5 <-- 5 keyframes | ||
321 | 0 | ||
322 | 0 | ||
323 | 0 | ||
324 | ... 5 Keyframe data blocks | ||
325 | */ | ||
326 | |||
327 | /* | ||
328 | 2 <-- 2 keyframes | ||
329 | 0 | ||
330 | 0 | ||
331 | 0 | ||
332 | .. 2 Keyframe data blocks | ||
333 | */ | ||
334 | if (!BitConverter.IsLittleEndian) | ||
335 | { | ||
336 | pJoint.Priority = Utils.BytesToInt(BinBVHUtil.EndianSwap(data, i, 4)); i += 4; // Joint Priority override? | ||
337 | rotationkeys = Utils.BytesToInt(BinBVHUtil.EndianSwap(data, i, 4)); i += 4; // How many rotation keyframes | ||
338 | } | ||
339 | else | ||
340 | { | ||
341 | pJoint.Priority = Utils.BytesToInt(data, i); i += 4; // Joint Priority override? | ||
342 | rotationkeys = Utils.BytesToInt(data, i); i += 4; // How many rotation keyframes | ||
343 | } | ||
344 | |||
345 | // argh! floats into two bytes!.. bad bad bad bad | ||
346 | // After fighting with it for a while.. -1, to 1 seems to give the best results | ||
347 | rotations = readKeys(data, ref i, rotationkeys, -1f, 1f); | ||
348 | for (int iter = 0; iter < rotations.Length; iter++) | ||
349 | { | ||
350 | rotations[iter].W = 1f - | ||
351 | (rotations[iter].key_element.X + rotations[iter].key_element.Y + | ||
352 | rotations[iter].key_element.Z); | ||
353 | } | ||
354 | |||
355 | |||
356 | if (!BitConverter.IsLittleEndian) | ||
357 | { | ||
358 | positionkeys = Utils.BytesToInt(BinBVHUtil.EndianSwap(data, i, 4)); i += 4; // How many position keyframes | ||
359 | } | ||
360 | else | ||
361 | { | ||
362 | positionkeys = Utils.BytesToInt(data, i); i += 4; // How many position keyframes | ||
363 | } | ||
364 | |||
365 | // Read in position keyframes | ||
366 | // argh! more floats into two bytes!.. *head desk* | ||
367 | // After fighting with it for a while.. -5, to 5 seems to give the best results | ||
368 | positions = readKeys(data, ref i, positionkeys, -5f, 5f); | ||
369 | |||
370 | pJoint.rotationkeys = rotations; | ||
371 | pJoint.positionkeys = positions; | ||
372 | |||
373 | return pJoint; | ||
374 | } | ||
375 | |||
376 | /// <summary> | ||
377 | /// Read Keyframes of a certain type | ||
378 | /// advance i | ||
379 | /// </summary> | ||
380 | /// <param name="data">Animation Byte array</param> | ||
381 | /// <param name="i">Offset in the Byte Array. Will be advanced</param> | ||
382 | /// <param name="keycount">Number of Keyframes</param> | ||
383 | /// <param name="min">Scaling Min to pass to the Uint16ToFloat method</param> | ||
384 | /// <param name="max">Scaling Max to pass to the Uint16ToFloat method</param> | ||
385 | /// <returns></returns> | ||
386 | private binBVHJointKey[] readKeys(byte[] data, ref int i, int keycount, float min, float max) | ||
387 | { | ||
388 | float x; | ||
389 | float y; | ||
390 | float z; | ||
391 | |||
392 | /* | ||
393 | 0.o, Float values in Two bytes.. this is just wrong >:( | ||
394 | 17 255 <-- Time Code | ||
395 | 17 255 <-- Time Code | ||
396 | 255 255 <-- X | ||
397 | 127 127 <-- X | ||
398 | 255 255 <-- Y | ||
399 | 127 127 <-- Y | ||
400 | 213 213 <-- Z | ||
401 | 142 142 <---Z | ||
402 | |||
403 | */ | ||
404 | |||
405 | binBVHJointKey[] m_keys = new binBVHJointKey[keycount]; | ||
406 | for (int j = 0; j < keycount; j++) | ||
407 | { | ||
408 | binBVHJointKey pJKey = new binBVHJointKey(); | ||
409 | if (!BitConverter.IsLittleEndian) | ||
410 | { | ||
411 | pJKey.time = Utils.UInt16ToFloat(BinBVHUtil.EndianSwap(data, i, 2), 0, InPoint, OutPoint); i += 2; | ||
412 | x = Utils.UInt16ToFloat(BinBVHUtil.EndianSwap(data, i, 2), 0, min, max); i += 2; | ||
413 | y = Utils.UInt16ToFloat(BinBVHUtil.EndianSwap(data, i, 2), 0, min, max); i += 2; | ||
414 | z = Utils.UInt16ToFloat(BinBVHUtil.EndianSwap(data, i, 2), 0, min, max); i += 2; | ||
415 | } | ||
416 | else | ||
417 | { | ||
418 | pJKey.time = Utils.UInt16ToFloat(data, i, InPoint, OutPoint); i += 2; | ||
419 | x = Utils.UInt16ToFloat(data, i, min, max); i += 2; | ||
420 | y = Utils.UInt16ToFloat(data, i, min, max); i += 2; | ||
421 | z = Utils.UInt16ToFloat(data, i, min, max); i += 2; | ||
422 | } | ||
423 | pJKey.key_element = new Vector3(x, y, z); | ||
424 | m_keys[j] = pJKey; | ||
425 | } | ||
426 | return m_keys; | ||
427 | } | ||
428 | |||
429 | |||
430 | |||
431 | } | ||
432 | /// <summary> | ||
433 | /// A Joint and it's associated meta data and keyframes | ||
434 | /// </summary> | ||
435 | public struct binBVHJoint | ||
436 | { | ||
437 | /// <summary> | ||
438 | /// Name of the Joint. Matches the avatar_skeleton.xml in client distros | ||
439 | /// </summary> | ||
440 | public string Name; | ||
441 | |||
442 | /// <summary> | ||
443 | /// Joint Animation Override? Was the same as the Priority in testing.. | ||
444 | /// </summary> | ||
445 | public int Priority; | ||
446 | |||
447 | /// <summary> | ||
448 | /// Array of Rotation Keyframes in order from earliest to latest | ||
449 | /// </summary> | ||
450 | public binBVHJointKey[] rotationkeys; | ||
451 | |||
452 | /// <summary> | ||
453 | /// Array of Position Keyframes in order from earliest to latest | ||
454 | /// This seems to only be for the Pelvis? | ||
455 | /// </summary> | ||
456 | public binBVHJointKey[] positionkeys; | ||
457 | |||
458 | |||
459 | |||
460 | public void WriteBytesToStream(BinaryWriter iostream, float InPoint, float OutPoint) | ||
461 | { | ||
462 | iostream.Write(BinBVHUtil.WriteNullTerminatedString(Name)); | ||
463 | iostream.Write(BinBVHUtil.ES(Utils.IntToBytes(Priority))); | ||
464 | iostream.Write(BinBVHUtil.ES(Utils.IntToBytes(rotationkeys.Length))); | ||
465 | for (int i=0;i<rotationkeys.Length;i++) | ||
466 | { | ||
467 | rotationkeys[i].WriteBytesToStream(iostream, InPoint, OutPoint, -1f, 1f); | ||
468 | } | ||
469 | iostream.Write(BinBVHUtil.ES(Utils.IntToBytes((positionkeys.Length)))); | ||
470 | for (int i = 0; i < positionkeys.Length; i++) | ||
471 | { | ||
472 | positionkeys[i].WriteBytesToStream(iostream, InPoint, OutPoint, -256f, 256f); | ||
473 | } | ||
474 | } | ||
475 | } | ||
476 | |||
477 | /// <summary> | ||
478 | /// A Joint Keyframe. This is either a position or a rotation. | ||
479 | /// </summary> | ||
480 | public struct binBVHJointKey | ||
481 | { | ||
482 | // Time in seconds for this keyframe. | ||
483 | public float time; | ||
484 | |||
485 | /// <summary> | ||
486 | /// Either a Vector3 position or a Vector3 Euler rotation | ||
487 | /// </summary> | ||
488 | public Vector3 key_element; | ||
489 | |||
490 | public float W; | ||
491 | |||
492 | public void WriteBytesToStream(BinaryWriter iostream, float InPoint, float OutPoint, float min, float max) | ||
493 | { | ||
494 | iostream.Write(BinBVHUtil.ES(Utils.UInt16ToBytes(BinBVHUtil.FloatToUInt16(time, InPoint, OutPoint)))); | ||
495 | iostream.Write(BinBVHUtil.ES(Utils.UInt16ToBytes(BinBVHUtil.FloatToUInt16(key_element.X, min, max)))); | ||
496 | iostream.Write(BinBVHUtil.ES(Utils.UInt16ToBytes(BinBVHUtil.FloatToUInt16(key_element.Y, min, max)))); | ||
497 | iostream.Write(BinBVHUtil.ES(Utils.UInt16ToBytes(BinBVHUtil.FloatToUInt16(key_element.Z, min, max)))); | ||
498 | } | ||
499 | } | ||
500 | |||
501 | /// <summary> | ||
502 | /// Poses set in the animation metadata for the hands. | ||
503 | /// </summary> | ||
504 | public enum HandPose : uint | ||
505 | { | ||
506 | Spread = 0, | ||
507 | Relaxed = 1, | ||
508 | Point_Both = 2, | ||
509 | Fist = 3, | ||
510 | Relaxed_Left = 4, | ||
511 | Point_Left = 5, | ||
512 | Fist_Left = 6, | ||
513 | Relaxed_Right = 7, | ||
514 | Point_Right = 8, | ||
515 | Fist_Right = 9, | ||
516 | Salute_Right = 10, | ||
517 | Typing = 11, | ||
518 | Peace_Right = 12 | ||
519 | } | ||
520 | public static class BinBVHUtil | ||
521 | { | ||
522 | public const float ONE_OVER_U16_MAX = 1.0f / UInt16.MaxValue; | ||
523 | |||
524 | public static UInt16 FloatToUInt16(float val, float lower, float upper) | ||
525 | { | ||
526 | UInt16 uival = 0; | ||
527 | //m_parentGroup.GetTimeDilation() * (float)ushort.MaxValue | ||
528 | //0-1 | ||
529 | |||
530 | // float difference = upper - lower; | ||
531 | // we're trying to get a zero lower and modify all values equally so we get a percentage position | ||
532 | if (lower > 0) | ||
533 | { | ||
534 | upper -= lower; | ||
535 | val = val - lower; | ||
536 | |||
537 | // start with 500 upper and 200 lower.. subtract 200 from the upper and the value | ||
538 | } | ||
539 | else //if (lower < 0 && upper > 0) | ||
540 | { | ||
541 | // double negative, 0 minus negative 5 is 5. | ||
542 | upper += 0 - lower; | ||
543 | lower += 0 - lower; | ||
544 | val += 0 - lower; | ||
545 | } | ||
546 | |||
547 | if (upper == 0) | ||
548 | val = 0; | ||
549 | else | ||
550 | { | ||
551 | val /= upper; | ||
552 | } | ||
553 | |||
554 | uival = (UInt16)(val * UInt16.MaxValue); | ||
555 | |||
556 | return uival; | ||
557 | } | ||
558 | |||
559 | |||
560 | /// <summary> | ||
561 | /// Endian Swap | ||
562 | /// Swaps endianness if necessary | ||
563 | /// </summary> | ||
564 | /// <param name="arr">Input array</param> | ||
565 | /// <returns></returns> | ||
566 | public static byte[] ES(byte[] arr) | ||
567 | { | ||
568 | if (!BitConverter.IsLittleEndian) | ||
569 | Array.Reverse(arr); | ||
570 | return arr; | ||
571 | } | ||
572 | public static byte[] EndianSwap(byte[] arr, int offset, int len) | ||
573 | { | ||
574 | byte[] bendian = new byte[offset + len]; | ||
575 | Buffer.BlockCopy(arr, offset, bendian, 0, len); | ||
576 | Array.Reverse(bendian); | ||
577 | return bendian; | ||
578 | } | ||
579 | |||
580 | public static byte[] WriteNullTerminatedString(string str) | ||
581 | { | ||
582 | byte[] output = new byte[str.Length + 1]; | ||
583 | Char[] chr = str.ToCharArray(); | ||
584 | int i = 0; | ||
585 | for (i = 0; i < chr.Length; i++) | ||
586 | { | ||
587 | output[i] = Convert.ToByte(chr[i]); | ||
588 | |||
589 | } | ||
590 | |||
591 | output[i] = Convert.ToByte('\0'); | ||
592 | return output; | ||
593 | } | ||
594 | |||
595 | } | ||
596 | } | ||
597 | /* | ||
598 | switch (jointname) | ||
599 | { | ||
600 | case "mPelvis": | ||
601 | case "mTorso": | ||
602 | case "mNeck": | ||
603 | case "mHead": | ||
604 | case "mChest": | ||
605 | case "mHipLeft": | ||
606 | case "mHipRight": | ||
607 | case "mKneeLeft": | ||
608 | case "mKneeRight": | ||
609 | // XYZ->ZXY | ||
610 | t = x; | ||
611 | x = y; | ||
612 | y = t; | ||
613 | break; | ||
614 | case "mCollarLeft": | ||
615 | case "mCollarRight": | ||
616 | case "mElbowLeft": | ||
617 | case "mElbowRight": | ||
618 | // YZX ->ZXY | ||
619 | t = z; | ||
620 | z = x; | ||
621 | x = y; | ||
622 | y = t; | ||
623 | break; | ||
624 | case "mWristLeft": | ||
625 | case "mWristRight": | ||
626 | case "mShoulderLeft": | ||
627 | case "mShoulderRight": | ||
628 | // ZYX->ZXY | ||
629 | t = y; | ||
630 | y = z; | ||
631 | z = t; | ||
632 | |||
633 | break; | ||
634 | case "mAnkleLeft": | ||
635 | case "mAnkleRight": | ||
636 | // XYZ ->ZXY | ||
637 | t = x; | ||
638 | x = z; | ||
639 | z = y; | ||
640 | y = t; | ||
641 | break; | ||
642 | } | ||
643 | */ \ No newline at end of file | ||