mirror of
https://github.com/TechplexEngineer/plexview.git
synced 2026-07-29 17:33:19 +00:00
Initial commit
I wish I could figure out how to have PlexVie be out of the LibOMV tree but its just not working die to a DLL not found exception about libopenjpeg. (Yes the dll is in the bin folder) This will do for now
This commit is contained in:
@@ -0,0 +1,559 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2014, openmetaverse.org
|
||||
* All rights reserved.
|
||||
*
|
||||
* - Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* - Neither the name of the openmetaverse.org nor the names
|
||||
* of its contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
using System;
|
||||
|
||||
namespace OpenMetaverse
|
||||
{
|
||||
/// <summary>
|
||||
/// Reads in a byte array of an Animation Asset created by the SecondLife(tm) client.
|
||||
/// </summary>
|
||||
public class BinBVHAnimationReader
|
||||
{
|
||||
/// <summary>
|
||||
/// Rotation Keyframe count (used internally)
|
||||
/// </summary>
|
||||
private int rotationkeys;
|
||||
|
||||
/// <summary>
|
||||
/// Position Keyframe count (used internally)
|
||||
/// </summary>
|
||||
private int positionkeys;
|
||||
|
||||
public UInt16 unknown0; // Always 1
|
||||
public UInt16 unknown1; // Always 0
|
||||
|
||||
/// <summary>
|
||||
/// Animation Priority
|
||||
/// </summary>
|
||||
public int Priority;
|
||||
|
||||
/// <summary>
|
||||
/// The animation length in seconds.
|
||||
/// </summary>
|
||||
public Single Length;
|
||||
|
||||
/// <summary>
|
||||
/// Expression set in the client. Null if [None] is selected
|
||||
/// </summary>
|
||||
public string ExpressionName; // "" (null)
|
||||
|
||||
/// <summary>
|
||||
/// The time in seconds to start the animation
|
||||
/// </summary>
|
||||
public Single InPoint;
|
||||
|
||||
/// <summary>
|
||||
/// The time in seconds to end the animation
|
||||
/// </summary>
|
||||
public Single OutPoint;
|
||||
|
||||
/// <summary>
|
||||
/// Loop the animation
|
||||
/// </summary>
|
||||
public bool Loop;
|
||||
|
||||
/// <summary>
|
||||
/// Meta data. Ease in Seconds.
|
||||
/// </summary>
|
||||
public Single EaseInTime;
|
||||
|
||||
/// <summary>
|
||||
/// Meta data. Ease out seconds.
|
||||
/// </summary>
|
||||
public Single EaseOutTime;
|
||||
|
||||
/// <summary>
|
||||
/// Meta Data for the Hand Pose
|
||||
/// </summary>
|
||||
public uint HandPose;
|
||||
|
||||
/// <summary>
|
||||
/// Number of joints defined in the animation
|
||||
/// </summary>
|
||||
public uint JointCount;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Contains an array of joints
|
||||
/// </summary>
|
||||
public binBVHJoint[] joints;
|
||||
|
||||
/// <summary>
|
||||
/// Searialize an animation asset into it's joints/keyframes/meta data
|
||||
/// </summary>
|
||||
/// <param name="animationdata"></param>
|
||||
public BinBVHAnimationReader(byte[] animationdata)
|
||||
{
|
||||
int i = 0;
|
||||
if (!BitConverter.IsLittleEndian)
|
||||
{
|
||||
unknown0 = Utils.BytesToUInt16(EndianSwap(animationdata, i, 2)); i += 2; // Always 1
|
||||
unknown1 = Utils.BytesToUInt16(EndianSwap(animationdata, i, 2)); i += 2; // Always 0
|
||||
Priority = Utils.BytesToInt(EndianSwap(animationdata, i, 4)); i += 4;
|
||||
Length = Utils.BytesToFloat(EndianSwap(animationdata, i, 4), 0); i += 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
unknown0 = Utils.BytesToUInt16(animationdata, i); i += 2; // Always 1
|
||||
unknown1 = Utils.BytesToUInt16(animationdata, i); i += 2; // Always 0
|
||||
Priority = Utils.BytesToInt(animationdata, i); i += 4;
|
||||
Length = Utils.BytesToFloat(animationdata, i); i += 4;
|
||||
}
|
||||
ExpressionName = ReadBytesUntilNull(animationdata, ref i);
|
||||
if (!BitConverter.IsLittleEndian)
|
||||
{
|
||||
InPoint = Utils.BytesToFloat(EndianSwap(animationdata, i, 4), 0); i += 4;
|
||||
OutPoint = Utils.BytesToFloat(EndianSwap(animationdata, i, 4), 0); i += 4;
|
||||
Loop = (Utils.BytesToInt(EndianSwap(animationdata, i, 4)) != 0); i += 4;
|
||||
EaseInTime = Utils.BytesToFloat(EndianSwap(animationdata, i, 4), 0); i += 4;
|
||||
EaseOutTime = Utils.BytesToFloat(EndianSwap(animationdata, i, 4), 0); i += 4;
|
||||
HandPose = Utils.BytesToUInt(EndianSwap(animationdata, i, 4)); i += 4; // Handpose?
|
||||
|
||||
JointCount = Utils.BytesToUInt(animationdata, i); i += 4; // Get Joint count
|
||||
}
|
||||
else
|
||||
{
|
||||
InPoint = Utils.BytesToFloat(animationdata, i); i += 4;
|
||||
OutPoint = Utils.BytesToFloat(animationdata, i); i += 4;
|
||||
Loop = (Utils.BytesToInt(animationdata, i) != 0); i += 4;
|
||||
EaseInTime = Utils.BytesToFloat(animationdata, i); i += 4;
|
||||
EaseOutTime = Utils.BytesToFloat(animationdata, i); i += 4;
|
||||
HandPose = Utils.BytesToUInt(animationdata, i); i += 4; // Handpose?
|
||||
|
||||
JointCount = Utils.BytesToUInt(animationdata, i); i += 4; // Get Joint count
|
||||
}
|
||||
joints = new binBVHJoint[JointCount];
|
||||
|
||||
// deserialize the number of joints in the animation.
|
||||
// Joints are variable length blocks of binary data consisting of joint data and keyframes
|
||||
for (int iter = 0; iter < JointCount; iter++)
|
||||
{
|
||||
binBVHJoint joint = readJoint(animationdata, ref i);
|
||||
joints[iter] = joint;
|
||||
}
|
||||
}
|
||||
|
||||
private byte[] EndianSwap(byte[] arr, int offset, int len)
|
||||
{
|
||||
byte[] bendian = new byte[offset + len];
|
||||
Buffer.BlockCopy(arr, offset, bendian, 0, len);
|
||||
Array.Reverse(bendian);
|
||||
return bendian;
|
||||
}
|
||||
/// <summary>
|
||||
/// Variable length strings seem to be null terminated in the animation asset.. but..
|
||||
/// use with caution, home grown.
|
||||
/// advances the index.
|
||||
/// </summary>
|
||||
/// <param name="data">The animation asset byte array</param>
|
||||
/// <param name="i">The offset to start reading</param>
|
||||
/// <returns>a string</returns>
|
||||
public string ReadBytesUntilNull(byte[] data, ref int i)
|
||||
{
|
||||
char nterm = '\0'; // Null terminator
|
||||
int endpos = i;
|
||||
int startpos = i;
|
||||
|
||||
// Find the null character
|
||||
for (int j = i; j < data.Length; j++)
|
||||
{
|
||||
char spot = Convert.ToChar(data[j]);
|
||||
if (spot == nterm)
|
||||
{
|
||||
endpos = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// if we got to the end, then it's a zero length string
|
||||
if (i == endpos)
|
||||
{
|
||||
// advance the 1 null character
|
||||
i++;
|
||||
return string.Empty;
|
||||
}
|
||||
else
|
||||
{
|
||||
// We found the end of the string
|
||||
// append the bytes from the beginning of the string to the end of the string
|
||||
// advance i
|
||||
byte[] interm = new byte[endpos - i];
|
||||
for (; i < endpos; i++)
|
||||
{
|
||||
interm[i - startpos] = data[i];
|
||||
}
|
||||
i++; // advance past the null character
|
||||
|
||||
return Utils.BytesToString(interm);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read in a Joint from an animation asset byte array
|
||||
/// Variable length Joint fields, yay!
|
||||
/// Advances the index
|
||||
/// </summary>
|
||||
/// <param name="data">animation asset byte array</param>
|
||||
/// <param name="i">Byte Offset of the start of the joint</param>
|
||||
/// <returns>The Joint data serialized into the binBVHJoint structure</returns>
|
||||
public binBVHJoint readJoint(byte[] data, ref int i)
|
||||
{
|
||||
|
||||
binBVHJointKey[] positions;
|
||||
binBVHJointKey[] rotations;
|
||||
|
||||
binBVHJoint pJoint = new binBVHJoint();
|
||||
|
||||
/*
|
||||
109
|
||||
84
|
||||
111
|
||||
114
|
||||
114
|
||||
111
|
||||
0 <--- Null terminator
|
||||
*/
|
||||
|
||||
pJoint.Name = ReadBytesUntilNull(data, ref i); // Joint name
|
||||
|
||||
/*
|
||||
2 <- Priority Revisited
|
||||
0
|
||||
0
|
||||
0
|
||||
*/
|
||||
|
||||
/*
|
||||
5 <-- 5 keyframes
|
||||
0
|
||||
0
|
||||
0
|
||||
... 5 Keyframe data blocks
|
||||
*/
|
||||
|
||||
/*
|
||||
2 <-- 2 keyframes
|
||||
0
|
||||
0
|
||||
0
|
||||
.. 2 Keyframe data blocks
|
||||
*/
|
||||
if (!BitConverter.IsLittleEndian)
|
||||
{
|
||||
pJoint.Priority = Utils.BytesToInt(EndianSwap(data, i, 4)); i += 4; // Joint Priority override?
|
||||
rotationkeys = Utils.BytesToInt(EndianSwap(data, i, 4)); i += 4; // How many rotation keyframes
|
||||
}
|
||||
else
|
||||
{
|
||||
pJoint.Priority = Utils.BytesToInt(data, i); i += 4; // Joint Priority override?
|
||||
rotationkeys = Utils.BytesToInt(data, i); i += 4; // How many rotation keyframes
|
||||
}
|
||||
|
||||
// Sanity check how many rotation keys there are
|
||||
if (rotationkeys < 0 || rotationkeys > 10000)
|
||||
{
|
||||
rotationkeys = 0;
|
||||
}
|
||||
|
||||
rotations = readKeys(data, ref i, rotationkeys, -1.0f, 1.0f);
|
||||
|
||||
if (!BitConverter.IsLittleEndian)
|
||||
{
|
||||
positionkeys = Utils.BytesToInt(EndianSwap(data, i, 4)); i += 4; // How many position keyframes
|
||||
}
|
||||
else
|
||||
{
|
||||
positionkeys = Utils.BytesToInt(data, i); i += 4; // How many position keyframes
|
||||
}
|
||||
|
||||
// Sanity check how many positions keys there are
|
||||
if (positionkeys < 0 || positionkeys > 10000)
|
||||
{
|
||||
positionkeys = 0;
|
||||
}
|
||||
|
||||
// Read in position keyframes
|
||||
positions = readKeys(data, ref i, positionkeys, -0.5f, 1.5f);
|
||||
|
||||
pJoint.rotationkeys = rotations;
|
||||
pJoint.positionkeys = positions;
|
||||
|
||||
return pJoint;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read Keyframes of a certain type
|
||||
/// advance i
|
||||
/// </summary>
|
||||
/// <param name="data">Animation Byte array</param>
|
||||
/// <param name="i">Offset in the Byte Array. Will be advanced</param>
|
||||
/// <param name="keycount">Number of Keyframes</param>
|
||||
/// <param name="min">Scaling Min to pass to the Uint16ToFloat method</param>
|
||||
/// <param name="max">Scaling Max to pass to the Uint16ToFloat method</param>
|
||||
/// <returns></returns>
|
||||
public binBVHJointKey[] readKeys(byte[] data, ref int i, int keycount, float min, float max)
|
||||
{
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
|
||||
/*
|
||||
17 255 <-- Time Code
|
||||
17 255 <-- Time Code
|
||||
255 255 <-- X
|
||||
127 127 <-- X
|
||||
255 255 <-- Y
|
||||
127 127 <-- Y
|
||||
213 213 <-- Z
|
||||
142 142 <---Z
|
||||
|
||||
*/
|
||||
|
||||
binBVHJointKey[] m_keys = new binBVHJointKey[keycount];
|
||||
for (int j = 0; j < keycount; j++)
|
||||
{
|
||||
binBVHJointKey pJKey = new binBVHJointKey();
|
||||
if (!BitConverter.IsLittleEndian)
|
||||
{
|
||||
pJKey.time = Utils.UInt16ToFloat(EndianSwap(data, i, 2), 0, InPoint, OutPoint); i += 2;
|
||||
x = Utils.UInt16ToFloat(EndianSwap(data, i, 2), 0, min, max); i += 2;
|
||||
y = Utils.UInt16ToFloat(EndianSwap(data, i, 2), 0, min, max); i += 2;
|
||||
z = Utils.UInt16ToFloat(EndianSwap(data, i, 2), 0, min, max); i += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
pJKey.time = Utils.UInt16ToFloat(data, i, InPoint, OutPoint); i += 2;
|
||||
x = Utils.UInt16ToFloat(data, i, min, max); i += 2;
|
||||
y = Utils.UInt16ToFloat(data, i, min, max); i += 2;
|
||||
z = Utils.UInt16ToFloat(data, i, min, max); i += 2;
|
||||
}
|
||||
pJKey.key_element = new Vector3(x, y, z);
|
||||
m_keys[j] = pJKey;
|
||||
}
|
||||
return m_keys;
|
||||
}
|
||||
|
||||
public bool Equals(BinBVHAnimationReader other)
|
||||
{
|
||||
if (ReferenceEquals(null, other)) return false;
|
||||
if (ReferenceEquals(this, other)) return true;
|
||||
return other.Loop.Equals(Loop) && other.OutPoint == OutPoint && other.InPoint == InPoint && other.Length == Length && other.HandPose == HandPose && other.JointCount == JointCount && Equals(other.joints, joints) && other.EaseInTime == EaseInTime && other.EaseOutTime == EaseOutTime && other.Priority == Priority && other.unknown1 == unknown1 && other.unknown0 == unknown0 && other.positionkeys == positionkeys && other.rotationkeys == rotationkeys;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the specified <see cref="T:System.Object"/> is equal to the current <see cref="T:System.Object"/>.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// true if the specified <see cref="T:System.Object"/> is equal to the current <see cref="T:System.Object"/>; otherwise, false.
|
||||
/// </returns>
|
||||
/// <param name="obj">The <see cref="T:System.Object"/> to compare with the current <see cref="T:System.Object"/>.
|
||||
/// </param><exception cref="T:System.NullReferenceException">The <paramref name="obj"/> parameter is null.
|
||||
/// </exception><filterpriority>2</filterpriority>
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (ReferenceEquals(null, obj)) return false;
|
||||
if (ReferenceEquals(this, obj)) return true;
|
||||
if (obj.GetType() != typeof(BinBVHAnimationReader)) return false;
|
||||
return Equals((BinBVHAnimationReader)obj);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Serves as a hash function for a particular type.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A hash code for the current <see cref="T:System.Object"/>.
|
||||
/// </returns>
|
||||
/// <filterpriority>2</filterpriority>
|
||||
public override int GetHashCode()
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
int result = Loop.GetHashCode();
|
||||
result = (result * 397) ^ OutPoint.GetHashCode();
|
||||
result = (result * 397) ^ InPoint.GetHashCode();
|
||||
result = (result * 397) ^ Length.GetHashCode();
|
||||
result = (result * 397) ^ HandPose.GetHashCode();
|
||||
result = (result * 397) ^ JointCount.GetHashCode();
|
||||
result = (result * 397) ^ (joints != null ? joints.GetHashCode() : 0);
|
||||
result = (result * 397) ^ EaseInTime.GetHashCode();
|
||||
result = (result * 397) ^ EaseOutTime.GetHashCode();
|
||||
result = (result * 397) ^ Priority;
|
||||
result = (result * 397) ^ unknown1.GetHashCode();
|
||||
result = (result * 397) ^ unknown0.GetHashCode();
|
||||
result = (result * 397) ^ positionkeys;
|
||||
result = (result * 397) ^ rotationkeys;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public static bool Equals(binBVHJoint[] arr1, binBVHJoint[] arr2)
|
||||
{
|
||||
if (arr1.Length == arr2.Length)
|
||||
{
|
||||
for (int i = 0; i < arr1.Length; i++)
|
||||
if (!arr1[i].Equals(arr2[i]))
|
||||
return false;
|
||||
/* not same*/
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A Joint and it's associated meta data and keyframes
|
||||
/// </summary>
|
||||
public struct binBVHJoint
|
||||
{
|
||||
public static bool Equals(binBVHJointKey[] arr1, binBVHJointKey[] arr2)
|
||||
{
|
||||
if (arr1.Length == arr2.Length)
|
||||
{
|
||||
for (int i = 0; i < arr1.Length; i++)
|
||||
if (!Equals(arr1[i], arr2[i]))
|
||||
return false;
|
||||
/* not same*/
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
public static bool Equals(binBVHJointKey arr1, binBVHJointKey arr2)
|
||||
{
|
||||
return (arr1.time == arr2.time && arr1.key_element == arr2.key_element);
|
||||
}
|
||||
|
||||
public bool Equals(binBVHJoint other)
|
||||
{
|
||||
return other.Priority == Priority && Equals(other.rotationkeys, rotationkeys) && Equals(other.Name, Name) && Equals(other.positionkeys, positionkeys);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicates whether this instance and a specified object are equal.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// true if <paramref name="obj"/> and this instance are the same type and represent the same value; otherwise, false.
|
||||
/// </returns>
|
||||
/// <param name="obj">Another object to compare to.
|
||||
/// </param><filterpriority>2</filterpriority>
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (ReferenceEquals(null, obj)) return false;
|
||||
if (obj.GetType() != typeof(binBVHJoint)) return false;
|
||||
return Equals((binBVHJoint)obj);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the hash code for this instance.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A 32-bit signed integer that is the hash code for this instance.
|
||||
/// </returns>
|
||||
/// <filterpriority>2</filterpriority>
|
||||
public override int GetHashCode()
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
int result = Priority;
|
||||
result = (result * 397) ^ (rotationkeys != null ? rotationkeys.GetHashCode() : 0);
|
||||
result = (result * 397) ^ (Name != null ? Name.GetHashCode() : 0);
|
||||
result = (result * 397) ^ (positionkeys != null ? positionkeys.GetHashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public static bool operator ==(binBVHJoint left, binBVHJoint right)
|
||||
{
|
||||
return left.Equals(right);
|
||||
}
|
||||
|
||||
public static bool operator !=(binBVHJoint left, binBVHJoint right)
|
||||
{
|
||||
return !left.Equals(right);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Name of the Joint. Matches the avatar_skeleton.xml in client distros
|
||||
/// </summary>
|
||||
public string Name;
|
||||
|
||||
/// <summary>
|
||||
/// Joint Animation Override? Was the same as the Priority in testing..
|
||||
/// </summary>
|
||||
public int Priority;
|
||||
|
||||
/// <summary>
|
||||
/// Array of Rotation Keyframes in order from earliest to latest
|
||||
/// </summary>
|
||||
public binBVHJointKey[] rotationkeys;
|
||||
|
||||
/// <summary>
|
||||
/// Array of Position Keyframes in order from earliest to latest
|
||||
/// This seems to only be for the Pelvis?
|
||||
/// </summary>
|
||||
public binBVHJointKey[] positionkeys;
|
||||
|
||||
/// <summary>
|
||||
/// Custom application data that can be attached to a joint
|
||||
/// </summary>
|
||||
public object Tag;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A Joint Keyframe. This is either a position or a rotation.
|
||||
/// </summary>
|
||||
public struct binBVHJointKey
|
||||
{
|
||||
// Time in seconds for this keyframe.
|
||||
public float time;
|
||||
|
||||
/// <summary>
|
||||
/// Either a Vector3 position or a Vector3 Euler rotation
|
||||
/// </summary>
|
||||
public Vector3 key_element;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Poses set in the animation metadata for the hands.
|
||||
/// </summary>
|
||||
public enum HandPose : uint
|
||||
{
|
||||
Spread = 0,
|
||||
Relaxed = 1,
|
||||
Point_Both = 2,
|
||||
Fist = 3,
|
||||
Relaxed_Left = 4,
|
||||
Point_Left = 5,
|
||||
Fist_Left = 6,
|
||||
Relaxed_Right = 7,
|
||||
Point_Right = 8,
|
||||
Fist_Right = 9,
|
||||
Salute_Right = 10,
|
||||
Typing = 11,
|
||||
Peace_Right = 12
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user