diff options
author | Teravus Ovares | 2009-03-09 04:33:53 +0000 |
---|---|---|
committer | Teravus Ovares | 2009-03-09 04:33:53 +0000 |
commit | f9ebdee1d249a1d8b5d0dac1787e1e40675d7784 (patch) | |
tree | 1a4aad566efb21da955c9c8fd18de0eda1f7df30 /OpenSim/Region/Framework | |
parent | Making the web_login_key code work, even if the LL Viewer doesn't support it.... (diff) | |
download | opensim-SC_OLD-f9ebdee1d249a1d8b5d0dac1787e1e40675d7784.zip opensim-SC_OLD-f9ebdee1d249a1d8b5d0dac1787e1e40675d7784.tar.gz opensim-SC_OLD-f9ebdee1d249a1d8b5d0dac1787e1e40675d7784.tar.bz2 opensim-SC_OLD-f9ebdee1d249a1d8b5d0dac1787e1e40675d7784.tar.xz |
* Tweak llMoveToTarget per mantis 3265
* Add some comments to the Wind Module
* Add the BinBVH decoder/encoder as a scene object (to encode/decode animations programmatically).
* Add m_sitState for upcoming code to improve sit results.
Diffstat (limited to '')
-rw-r--r-- | OpenSim/Region/Framework/Scenes/BinBVHAnimation.cs | 635 | ||||
-rw-r--r-- | OpenSim/Region/Framework/Scenes/ScenePresence.cs | 100 |
2 files changed, 732 insertions, 3 deletions
diff --git a/OpenSim/Region/Framework/Scenes/BinBVHAnimation.cs b/OpenSim/Region/Framework/Scenes/BinBVHAnimation.cs new file mode 100644 index 0000000..54f6d68 --- /dev/null +++ b/OpenSim/Region/Framework/Scenes/BinBVHAnimation.cs | |||
@@ -0,0 +1,635 @@ | |||
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 OpenSim 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 | ||
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 | |||
349 | |||
350 | if (!BitConverter.IsLittleEndian) | ||
351 | { | ||
352 | positionkeys = Utils.BytesToInt(BinBVHUtil.EndianSwap(data, i, 4)); i += 4; // How many position keyframes | ||
353 | } | ||
354 | else | ||
355 | { | ||
356 | positionkeys = Utils.BytesToInt(data, i); i += 4; // How many position keyframes | ||
357 | } | ||
358 | |||
359 | // Read in position keyframes | ||
360 | // argh! more floats into two bytes!.. *head desk* | ||
361 | // After fighting with it for a while.. -5, to 5 seems to give the best results | ||
362 | positions = readKeys(data, ref i, positionkeys, -5f, 5f); | ||
363 | |||
364 | pJoint.rotationkeys = rotations; | ||
365 | pJoint.positionkeys = positions; | ||
366 | |||
367 | return pJoint; | ||
368 | } | ||
369 | |||
370 | /// <summary> | ||
371 | /// Read Keyframes of a certain type | ||
372 | /// advance i | ||
373 | /// </summary> | ||
374 | /// <param name="data">Animation Byte array</param> | ||
375 | /// <param name="i">Offset in the Byte Array. Will be advanced</param> | ||
376 | /// <param name="keycount">Number of Keyframes</param> | ||
377 | /// <param name="min">Scaling Min to pass to the Uint16ToFloat method</param> | ||
378 | /// <param name="max">Scaling Max to pass to the Uint16ToFloat method</param> | ||
379 | /// <returns></returns> | ||
380 | private binBVHJointKey[] readKeys(byte[] data, ref int i, int keycount, float min, float max) | ||
381 | { | ||
382 | float x; | ||
383 | float y; | ||
384 | float z; | ||
385 | |||
386 | /* | ||
387 | 0.o, Float values in Two bytes.. this is just wrong >:( | ||
388 | 17 255 <-- Time Code | ||
389 | 17 255 <-- Time Code | ||
390 | 255 255 <-- X | ||
391 | 127 127 <-- X | ||
392 | 255 255 <-- Y | ||
393 | 127 127 <-- Y | ||
394 | 213 213 <-- Z | ||
395 | 142 142 <---Z | ||
396 | |||
397 | */ | ||
398 | |||
399 | binBVHJointKey[] m_keys = new binBVHJointKey[keycount]; | ||
400 | for (int j = 0; j < keycount; j++) | ||
401 | { | ||
402 | binBVHJointKey pJKey = new binBVHJointKey(); | ||
403 | if (!BitConverter.IsLittleEndian) | ||
404 | { | ||
405 | pJKey.time = Utils.UInt16ToFloat(BinBVHUtil.EndianSwap(data, i, 2), 0, InPoint, OutPoint); i += 2; | ||
406 | x = Utils.UInt16ToFloat(BinBVHUtil.EndianSwap(data, i, 2), 0, min, max); i += 2; | ||
407 | y = Utils.UInt16ToFloat(BinBVHUtil.EndianSwap(data, i, 2), 0, min, max); i += 2; | ||
408 | z = Utils.UInt16ToFloat(BinBVHUtil.EndianSwap(data, i, 2), 0, min, max); i += 2; | ||
409 | } | ||
410 | else | ||
411 | { | ||
412 | pJKey.time = Utils.UInt16ToFloat(data, i, InPoint, OutPoint); i += 2; | ||
413 | x = Utils.UInt16ToFloat(data, i, min, max); i += 2; | ||
414 | y = Utils.UInt16ToFloat(data, i, min, max); i += 2; | ||
415 | z = Utils.UInt16ToFloat(data, i, min, max); i += 2; | ||
416 | } | ||
417 | pJKey.key_element = new Vector3(x, y, z); | ||
418 | m_keys[j] = pJKey; | ||
419 | } | ||
420 | return m_keys; | ||
421 | } | ||
422 | |||
423 | |||
424 | |||
425 | } | ||
426 | /// <summary> | ||
427 | /// A Joint and it's associated meta data and keyframes | ||
428 | /// </summary> | ||
429 | public struct binBVHJoint | ||
430 | { | ||
431 | /// <summary> | ||
432 | /// Name of the Joint. Matches the avatar_skeleton.xml in client distros | ||
433 | /// </summary> | ||
434 | public string Name; | ||
435 | |||
436 | /// <summary> | ||
437 | /// Joint Animation Override? Was the same as the Priority in testing.. | ||
438 | /// </summary> | ||
439 | public int Priority; | ||
440 | |||
441 | /// <summary> | ||
442 | /// Array of Rotation Keyframes in order from earliest to latest | ||
443 | /// </summary> | ||
444 | public binBVHJointKey[] rotationkeys; | ||
445 | |||
446 | /// <summary> | ||
447 | /// Array of Position Keyframes in order from earliest to latest | ||
448 | /// This seems to only be for the Pelvis? | ||
449 | /// </summary> | ||
450 | public binBVHJointKey[] positionkeys; | ||
451 | |||
452 | |||
453 | |||
454 | public void WriteBytesToStream(BinaryWriter iostream, float InPoint, float OutPoint) | ||
455 | { | ||
456 | iostream.Write(BinBVHUtil.WriteNullTerminatedString(Name)); | ||
457 | iostream.Write(BinBVHUtil.ES(Utils.IntToBytes(Priority))); | ||
458 | iostream.Write(BinBVHUtil.ES(Utils.IntToBytes(rotationkeys.Length))); | ||
459 | for (int i=0;i<rotationkeys.Length;i++) | ||
460 | { | ||
461 | rotationkeys[i].WriteBytesToStream(iostream, InPoint, OutPoint, -1f, 1f); | ||
462 | } | ||
463 | iostream.Write(BinBVHUtil.ES(Utils.IntToBytes((positionkeys.Length)))); | ||
464 | for (int i = 0; i < positionkeys.Length; i++) | ||
465 | { | ||
466 | positionkeys[i].WriteBytesToStream(iostream, InPoint, OutPoint, -256f, 256f); | ||
467 | } | ||
468 | } | ||
469 | } | ||
470 | |||
471 | /// <summary> | ||
472 | /// A Joint Keyframe. This is either a position or a rotation. | ||
473 | /// </summary> | ||
474 | public struct binBVHJointKey | ||
475 | { | ||
476 | // Time in seconds for this keyframe. | ||
477 | public float time; | ||
478 | |||
479 | /// <summary> | ||
480 | /// Either a Vector3 position or a Vector3 Euler rotation | ||
481 | /// </summary> | ||
482 | public Vector3 key_element; | ||
483 | |||
484 | public void WriteBytesToStream(BinaryWriter iostream, float InPoint, float OutPoint, float min, float max) | ||
485 | { | ||
486 | iostream.Write(BinBVHUtil.ES(Utils.UInt16ToBytes(BinBVHUtil.FloatToUInt16(time, InPoint, OutPoint)))); | ||
487 | iostream.Write(BinBVHUtil.ES(Utils.UInt16ToBytes(BinBVHUtil.FloatToUInt16(key_element.X, min, max)))); | ||
488 | iostream.Write(BinBVHUtil.ES(Utils.UInt16ToBytes(BinBVHUtil.FloatToUInt16(key_element.Y, min, max)))); | ||
489 | iostream.Write(BinBVHUtil.ES(Utils.UInt16ToBytes(BinBVHUtil.FloatToUInt16(key_element.Z, min, max)))); | ||
490 | } | ||
491 | } | ||
492 | |||
493 | /// <summary> | ||
494 | /// Poses set in the animation metadata for the hands. | ||
495 | /// </summary> | ||
496 | public enum HandPose : uint | ||
497 | { | ||
498 | Spread = 0, | ||
499 | Relaxed = 1, | ||
500 | Point_Both = 2, | ||
501 | Fist = 3, | ||
502 | Relaxed_Left = 4, | ||
503 | Point_Left = 5, | ||
504 | Fist_Left = 6, | ||
505 | Relaxed_Right = 7, | ||
506 | Point_Right = 8, | ||
507 | Fist_Right = 9, | ||
508 | Salute_Right = 10, | ||
509 | Typing = 11, | ||
510 | Peace_Right = 12 | ||
511 | } | ||
512 | public static class BinBVHUtil | ||
513 | { | ||
514 | public const float ONE_OVER_U16_MAX = 1.0f / UInt16.MaxValue; | ||
515 | |||
516 | public static UInt16 FloatToUInt16(float val, float lower, float upper) | ||
517 | { | ||
518 | UInt16 uival = 0; | ||
519 | //m_parentGroup.GetTimeDilation() * (float)ushort.MaxValue | ||
520 | //0-1 | ||
521 | |||
522 | float difference = upper - lower; | ||
523 | // we're trying to get a zero lower and modify all values equally so we get a percentage position | ||
524 | if (lower > 0) | ||
525 | { | ||
526 | upper -= lower; | ||
527 | val = val - lower; | ||
528 | |||
529 | // start with 500 upper and 200 lower.. subtract 200 from the upper and the value | ||
530 | } | ||
531 | else //if (lower < 0 && upper > 0) | ||
532 | { | ||
533 | // double negative, 0 minus negative 5 is 5. | ||
534 | upper += 0 - lower; | ||
535 | lower += 0 - lower; | ||
536 | val += 0 - lower; | ||
537 | } | ||
538 | |||
539 | if (upper == 0) | ||
540 | val = 0; | ||
541 | else | ||
542 | { | ||
543 | val /= upper; | ||
544 | } | ||
545 | |||
546 | uival = (UInt16)(val * UInt16.MaxValue); | ||
547 | |||
548 | return uival; | ||
549 | } | ||
550 | |||
551 | |||
552 | /// <summary> | ||
553 | /// Endian Swap | ||
554 | /// Swaps endianness if necessary | ||
555 | /// </summary> | ||
556 | /// <param name="arr">Input array</param> | ||
557 | /// <returns></returns> | ||
558 | public static byte[] ES(byte[] arr) | ||
559 | { | ||
560 | if (!BitConverter.IsLittleEndian) | ||
561 | Array.Reverse(arr); | ||
562 | return arr; | ||
563 | } | ||
564 | public static byte[] EndianSwap(byte[] arr, int offset, int len) | ||
565 | { | ||
566 | byte[] bendian = new byte[offset + len]; | ||
567 | Buffer.BlockCopy(arr, offset, bendian, 0, len); | ||
568 | Array.Reverse(bendian); | ||
569 | return bendian; | ||
570 | } | ||
571 | |||
572 | public static byte[] WriteNullTerminatedString(string str) | ||
573 | { | ||
574 | byte[] output = new byte[str.Length + 1]; | ||
575 | Char[] chr = str.ToCharArray(); | ||
576 | int i = 0; | ||
577 | for (i = 0; i < chr.Length; i++) | ||
578 | { | ||
579 | output[i] = Convert.ToByte(chr[i]); | ||
580 | |||
581 | } | ||
582 | |||
583 | output[i] = Convert.ToByte('\0'); | ||
584 | return output; | ||
585 | } | ||
586 | |||
587 | } | ||
588 | } | ||
589 | /* | ||
590 | switch (jointname) | ||
591 | { | ||
592 | case "mPelvis": | ||
593 | case "mTorso": | ||
594 | case "mNeck": | ||
595 | case "mHead": | ||
596 | case "mChest": | ||
597 | case "mHipLeft": | ||
598 | case "mHipRight": | ||
599 | case "mKneeLeft": | ||
600 | case "mKneeRight": | ||
601 | // XYZ->ZXY | ||
602 | t = x; | ||
603 | x = y; | ||
604 | y = t; | ||
605 | break; | ||
606 | case "mCollarLeft": | ||
607 | case "mCollarRight": | ||
608 | case "mElbowLeft": | ||
609 | case "mElbowRight": | ||
610 | // YZX ->ZXY | ||
611 | t = z; | ||
612 | z = x; | ||
613 | x = y; | ||
614 | y = t; | ||
615 | break; | ||
616 | case "mWristLeft": | ||
617 | case "mWristRight": | ||
618 | case "mShoulderLeft": | ||
619 | case "mShoulderRight": | ||
620 | // ZYX->ZXY | ||
621 | t = y; | ||
622 | y = z; | ||
623 | z = t; | ||
624 | |||
625 | break; | ||
626 | case "mAnkleLeft": | ||
627 | case "mAnkleRight": | ||
628 | // XYZ ->ZXY | ||
629 | t = x; | ||
630 | x = z; | ||
631 | z = y; | ||
632 | y = t; | ||
633 | break; | ||
634 | } | ||
635 | */ \ No newline at end of file | ||
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 5160e73..5831ff4 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs | |||
@@ -119,6 +119,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
119 | 119 | ||
120 | private int m_perfMonMS = 0; | 120 | private int m_perfMonMS = 0; |
121 | 121 | ||
122 | private bool m_sitStatus = false; | ||
123 | |||
122 | private bool m_setAlwaysRun = false; | 124 | private bool m_setAlwaysRun = false; |
123 | 125 | ||
124 | private Quaternion m_bodyRot= Quaternion.Identity; | 126 | private Quaternion m_bodyRot= Quaternion.Identity; |
@@ -567,7 +569,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
567 | m_firstname = m_controllingClient.FirstName; | 569 | m_firstname = m_controllingClient.FirstName; |
568 | m_lastname = m_controllingClient.LastName; | 570 | m_lastname = m_controllingClient.LastName; |
569 | m_name = String.Format("{0} {1}", m_firstname, m_lastname); | 571 | m_name = String.Format("{0} {1}", m_firstname, m_lastname); |
570 | 572 | if (DateTime.Now.Month==4&&DateTime.Now.Day==1) | |
573 | m_sitStatus = true; | ||
571 | m_scene = world; | 574 | m_scene = world; |
572 | m_uuid = client.AgentId; | 575 | m_uuid = client.AgentId; |
573 | m_regionInfo = reginfo; | 576 | m_regionInfo = reginfo; |
@@ -600,11 +603,15 @@ namespace OpenSim.Region.Framework.Scenes | |||
600 | : this(client, world, reginfo) | 603 | : this(client, world, reginfo) |
601 | { | 604 | { |
602 | m_appearance = new AvatarAppearance(m_uuid, wearables, visualParams); | 605 | m_appearance = new AvatarAppearance(m_uuid, wearables, visualParams); |
606 | if (DateTime.Now.Month==4&&DateTime.Now.Day==1) | ||
607 | m_sitStatus = true; | ||
603 | } | 608 | } |
604 | 609 | ||
605 | public ScenePresence(IClientAPI client, Scene world, RegionInfo reginfo, AvatarAppearance appearance) | 610 | public ScenePresence(IClientAPI client, Scene world, RegionInfo reginfo, AvatarAppearance appearance) |
606 | : this(client, world, reginfo) | 611 | : this(client, world, reginfo) |
607 | { | 612 | { |
613 | if (DateTime.Now.Month==4&&DateTime.Now.Day==1) | ||
614 | m_sitStatus = true; | ||
608 | m_appearance = appearance; | 615 | m_appearance = appearance; |
609 | } | 616 | } |
610 | 617 | ||
@@ -1144,8 +1151,17 @@ namespace OpenSim.Region.Framework.Scenes | |||
1144 | { | 1151 | { |
1145 | StandUp(); | 1152 | StandUp(); |
1146 | } | 1153 | } |
1154 | |||
1155 | |||
1156 | |||
1147 | m_mouseLook = (flags & (uint) AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0; | 1157 | m_mouseLook = (flags & (uint) AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0; |
1158 | |||
1159 | |||
1160 | |||
1148 | m_leftButtonDown = (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_DOWN) != 0; | 1161 | m_leftButtonDown = (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_DOWN) != 0; |
1162 | |||
1163 | |||
1164 | |||
1149 | lock (scriptedcontrols) | 1165 | lock (scriptedcontrols) |
1150 | { | 1166 | { |
1151 | if (scriptedcontrols.Count > 0) | 1167 | if (scriptedcontrols.Count > 0) |
@@ -1788,7 +1804,70 @@ namespace OpenSim.Region.Framework.Scenes | |||
1788 | PhysicsActor.SetAlwaysRun = SetAlwaysRun; | 1804 | PhysicsActor.SetAlwaysRun = SetAlwaysRun; |
1789 | } | 1805 | } |
1790 | } | 1806 | } |
1791 | 1807 | public BinBVHAnimation GenerateRandomAnimation() | |
1808 | { | ||
1809 | int rnditerations = 3; | ||
1810 | BinBVHAnimation anim = new BinBVHAnimation(); | ||
1811 | List<string> parts = new List<string>(); | ||
1812 | parts.Add("mPelvis");parts.Add("mHead");parts.Add("mTorso"); | ||
1813 | parts.Add("mHipLeft");parts.Add("mHipRight");parts.Add("mHipLeft");parts.Add("mKneeLeft"); | ||
1814 | parts.Add("mKneeRight");parts.Add("mCollarLeft");parts.Add("mCollarRight");parts.Add("mNeck"); | ||
1815 | parts.Add("mElbowLeft");parts.Add("mElbowRight");parts.Add("mWristLeft");parts.Add("mWristRight"); | ||
1816 | parts.Add("mShoulderLeft");parts.Add("mShoulderRight");parts.Add("mAnkleLeft");parts.Add("mAnkleRight"); | ||
1817 | parts.Add("mEyeRight");parts.Add("mChest");parts.Add("mToeLeft");parts.Add("mToeRight"); | ||
1818 | parts.Add("mFootLeft");parts.Add("mFootRight");parts.Add("mEyeLeft"); | ||
1819 | anim.HandPose = 1; | ||
1820 | anim.InPoint = 0; | ||
1821 | anim.OutPoint = (rnditerations * .10f); | ||
1822 | anim.Priority = 7; | ||
1823 | anim.Loop = false; | ||
1824 | anim.Length = (rnditerations * .10f); | ||
1825 | anim.ExpressionName = "afraid"; | ||
1826 | anim.EaseInTime = 0; | ||
1827 | anim.EaseOutTime = 0; | ||
1828 | |||
1829 | string[] strjoints = parts.ToArray(); | ||
1830 | anim.Joints = new binBVHJoint[strjoints.Length]; | ||
1831 | for (int j = 0; j < strjoints.Length; j++) | ||
1832 | { | ||
1833 | anim.Joints[j] = new binBVHJoint(); | ||
1834 | anim.Joints[j].Name = strjoints[j]; | ||
1835 | anim.Joints[j].Priority = 7; | ||
1836 | anim.Joints[j].positionkeys = new binBVHJointKey[rnditerations]; | ||
1837 | anim.Joints[j].rotationkeys = new binBVHJointKey[rnditerations]; | ||
1838 | Random rnd = new Random(); | ||
1839 | for (int i = 0; i < rnditerations; i++) | ||
1840 | { | ||
1841 | anim.Joints[j].rotationkeys[i] = new binBVHJointKey(); | ||
1842 | anim.Joints[j].rotationkeys[i].time = (i*.10f); | ||
1843 | anim.Joints[j].rotationkeys[i].key_element.X = ((float) rnd.NextDouble()*2 - 1); | ||
1844 | anim.Joints[j].rotationkeys[i].key_element.Y = ((float) rnd.NextDouble()*2 - 1); | ||
1845 | anim.Joints[j].rotationkeys[i].key_element.Z = ((float) rnd.NextDouble()*2 - 1); | ||
1846 | anim.Joints[j].positionkeys[i] = new binBVHJointKey(); | ||
1847 | anim.Joints[j].positionkeys[i].time = (i*.10f); | ||
1848 | anim.Joints[j].positionkeys[i].key_element.X = 0; | ||
1849 | anim.Joints[j].positionkeys[i].key_element.Y = 0; | ||
1850 | anim.Joints[j].positionkeys[i].key_element.Z = 0; | ||
1851 | } | ||
1852 | } | ||
1853 | |||
1854 | |||
1855 | AssetBase Animasset = new AssetBase(); | ||
1856 | Animasset.Data = anim.ToBytes(); | ||
1857 | Animasset.Temporary = true; | ||
1858 | Animasset.Local = true; | ||
1859 | Animasset.FullID = UUID.Random(); | ||
1860 | Animasset.ID = Animasset.FullID.ToString(); | ||
1861 | Animasset.Name = "Random Animation"; | ||
1862 | Animasset.Type = (sbyte)AssetType.Animation; | ||
1863 | Animasset.Description = "dance"; | ||
1864 | //BinBVHAnimation bbvhanim = new BinBVHAnimation(Animasset.Data); | ||
1865 | |||
1866 | |||
1867 | m_scene.CommsManager.AssetCache.AddAsset(Animasset); | ||
1868 | AddAnimation(Animasset.FullID, UUID); | ||
1869 | return anim; | ||
1870 | } | ||
1792 | public void AddAnimation(UUID animID, UUID objectID) | 1871 | public void AddAnimation(UUID animID, UUID objectID) |
1793 | { | 1872 | { |
1794 | if (m_isChildAgent) | 1873 | if (m_isChildAgent) |
@@ -2159,6 +2238,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
2159 | remoteAvatar.m_controllingClient.SendAvatarData(m_regionInfo.RegionHandle, m_firstname, m_lastname, m_grouptitle, m_uuid, | 2238 | remoteAvatar.m_controllingClient.SendAvatarData(m_regionInfo.RegionHandle, m_firstname, m_lastname, m_grouptitle, m_uuid, |
2160 | LocalId, m_pos, m_appearance.Texture.ToBytes(), | 2239 | LocalId, m_pos, m_appearance.Texture.ToBytes(), |
2161 | m_parentID, rot); | 2240 | m_parentID, rot); |
2241 | if (m_sitStatus) | ||
2242 | GenerateRandomAnimation(); | ||
2162 | m_scene.AddAgentUpdates(1); | 2243 | m_scene.AddAgentUpdates(1); |
2163 | } | 2244 | } |
2164 | 2245 | ||
@@ -2175,6 +2256,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
2175 | // only send if this is the root (children are only "listening posts" in a foreign region) | 2256 | // only send if this is the root (children are only "listening posts" in a foreign region) |
2176 | if (!IsChildAgent) | 2257 | if (!IsChildAgent) |
2177 | { | 2258 | { |
2259 | if (m_sitStatus) | ||
2260 | GenerateRandomAnimation(); | ||
2178 | SendFullUpdateToOtherClient(avatar); | 2261 | SendFullUpdateToOtherClient(avatar); |
2179 | } | 2262 | } |
2180 | 2263 | ||
@@ -2182,8 +2265,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
2182 | { | 2265 | { |
2183 | if (!avatar.IsChildAgent) | 2266 | if (!avatar.IsChildAgent) |
2184 | { | 2267 | { |
2268 | m_log.Debug(DateTime.Now.ToString()); | ||
2185 | avatar.SendFullUpdateToOtherClient(this); | 2269 | avatar.SendFullUpdateToOtherClient(this); |
2186 | avatar.SendAppearanceToOtherAgent(this); | 2270 | avatar.SendAppearanceToOtherAgent(this); |
2271 | if (m_sitStatus) | ||
2272 | GenerateRandomAnimation(); | ||
2187 | avatar.SendAnimPackToClient(this.ControllingClient); | 2273 | avatar.SendAnimPackToClient(this.ControllingClient); |
2188 | } | 2274 | } |
2189 | } | 2275 | } |
@@ -2198,6 +2284,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
2198 | { | 2284 | { |
2199 | m_perfMonMS = System.Environment.TickCount; | 2285 | m_perfMonMS = System.Environment.TickCount; |
2200 | 2286 | ||
2287 | if (m_sitStatus) | ||
2288 | GenerateRandomAnimation(); | ||
2201 | // only send update from root agents to other clients; children are only "listening posts" | 2289 | // only send update from root agents to other clients; children are only "listening posts" |
2202 | List<ScenePresence> avatars = m_scene.GetAvatars(); | 2290 | List<ScenePresence> avatars = m_scene.GetAvatars(); |
2203 | foreach (ScenePresence avatar in avatars) | 2291 | foreach (ScenePresence avatar in avatars) |
@@ -2421,6 +2509,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
2421 | m_LastChildAgentUpdatePosition.X = AbsolutePosition.X; | 2509 | m_LastChildAgentUpdatePosition.X = AbsolutePosition.X; |
2422 | m_LastChildAgentUpdatePosition.Y = AbsolutePosition.Y; | 2510 | m_LastChildAgentUpdatePosition.Y = AbsolutePosition.Y; |
2423 | m_LastChildAgentUpdatePosition.Z = AbsolutePosition.Z; | 2511 | m_LastChildAgentUpdatePosition.Z = AbsolutePosition.Z; |
2512 | |||
2513 | if (m_sitStatus) | ||
2514 | GenerateRandomAnimation(); | ||
2424 | } | 2515 | } |
2425 | } | 2516 | } |
2426 | 2517 | ||
@@ -2832,6 +2923,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2832 | { | 2923 | { |
2833 | Primitive.TextureEntry textu = AvatarAppearance.GetDefaultTexture(); | 2924 | Primitive.TextureEntry textu = AvatarAppearance.GetDefaultTexture(); |
2834 | DefaultTexture = textu.ToBytes(); | 2925 | DefaultTexture = textu.ToBytes(); |
2926 | |||
2835 | } | 2927 | } |
2836 | 2928 | ||
2837 | public class NewForce | 2929 | public class NewForce |
@@ -2970,7 +3062,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
2970 | { | 3062 | { |
2971 | Primitive.TextureEntry textu = AvatarAppearance.GetDefaultTexture(); | 3063 | Primitive.TextureEntry textu = AvatarAppearance.GetDefaultTexture(); |
2972 | DefaultTexture = textu.ToBytes(); | 3064 | DefaultTexture = textu.ToBytes(); |
2973 | } | 3065 | } |
3066 | if (DateTime.Now.Month==4&&DateTime.Now.Day==1) | ||
3067 | m_sitStatus = true; | ||
2974 | } | 3068 | } |
2975 | 3069 | ||
2976 | public void AddAttachment(SceneObjectGroup gobj) | 3070 | public void AddAttachment(SceneObjectGroup gobj) |