public QJoint FindJointByIndex(int idx) { QJoint result = hierarchy; if (result.index == idx) { return(result); } List <QJoint> remaining = new List <QJoint>(); List <QJoint> nextBatch = new List <QJoint>(); remaining.AddRange(result.children); do { var jEnum = remaining.GetEnumerator(); while (jEnum.MoveNext()) { QJoint joint = jEnum.Current; if (joint.index == idx) { return(joint); } nextBatch.AddRange(joint.children); } jEnum.Dispose(); remaining = new List <QJoint>(nextBatch); nextBatch.Clear(); }while (remaining.Count > 0); Debug.LogError("joint index not found!"); return(null); }
public QAnimation(float _length, HashSet <string> _jointNames, QJoint _hierarchy, Dictionary <string, KeyBlob> _keyFrames) { length = _length; hierarchy = _hierarchy; jointNames = _jointNames; keyFrames = _keyFrames; }
private void AddJointsToArray(QJoint headJoint, Matrix4x4[] jointArray) { //jointArray[headJoint.index] = headJoint.animatedTransform; foreach (QJoint joint in headJoint.children) { AddJointsToArray(joint, jointArray); } }
public QModel(Mesh _mesh, Material _material, QJoint _rootJoint, int _jointCount) { mesh = _mesh; material = _material; rootJoint = _rootJoint; jointCount = _jointCount; //rootJoint.CalculateInverseTransform(new Matrix4x4()); }
QJoint SiftChildren(QJoint parent, string targetName) { foreach (QJoint child in parent.children) { if (child.name == targetName) { return(child); } } return(null); }
void ApplyPoseToJoints(Dictionary <string, Matrix4x4> currentPose, QJoint joint, Matrix4x4 parentTransform) { Matrix4x4 currentLocalTransform = currentPose[joint.name]; Matrix4x4 currentTransform = parentTransform * currentLocalTransform; foreach (QJoint child in joint.children) { ApplyPoseToJoints(currentPose, child, currentTransform); } //currentTransform *= joint.GetInverseBindTransform(); //joint.animatedTransform = currentTransform; }
public QAnimation LoadBagel(string path) { int jointIndex = 0; string bagelData = System.IO.File.ReadAllText(path); string[] jointBlocks = bagelData.Split(new[] { "&$*" }, StringSplitOptions.RemoveEmptyEntries); float animationLength = -1f; Matrix4x4[] bindXForms = model.bindposes; for (int i = 0; i < jointBlocks.Length; i++) { string jointBlock = jointBlocks[i]; string[] lines = jointBlock.Split('\n'); //we offset the base index since the first jointblock has the //animation length encoded in the 0th line int baseIndex = i == 0 ? 1 : 0; if (i == 0) { animationLength = float.Parse(lines[0]); } string jointPath = lines[baseIndex]; string[] hierarchyOrder = jointPath.Split(new[] { '/', '\r' }, StringSplitOptions.RemoveEmptyEntries); string jointName = hierarchyOrder[hierarchyOrder.Length - 1]; jointNames.Add(jointName); scalarBlobs.Add(jointName, new Dictionary <string, ScalarBlob>()); //case on whether we are reading the root if (hierarchy == null) { hierarchy = new QJoint(jointIndex, jointName, bindXForms[jointIndex]); jointIndex++; } else { QJoint hierarchyWalker = hierarchy; int hierarchyIndex = 1; while (hierarchyIndex < hierarchyOrder.Length - 1) { hierarchyWalker = SiftChildren(hierarchyWalker, hierarchyOrder[hierarchyIndex++]); } //Matrix4x4 localBind = bindXForms[hierarchyWalker.index] * bindXForms[jointIndex].inverse; //int startIdx = jointName.IndexOfAny(new[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' }); //string numSub = jointName.Substring(startIdx); //jointIndex = int.Parse(numSub) - 1; QJoint newJoint = hierarchyWalker; if (jointIndex != 0) { newJoint = new QJoint(jointIndex, jointName, bindXForms[jointIndex]); hierarchyWalker.AddChild(newJoint); } jointIndex++; } //parsing keyframes for each attribute string[] animatedAttributes = jointBlock.Split(new[] { "#_#" }, StringSplitOptions.None); //we ignore the 0th entry in animatedAttributes since that will contain the information that //we just parsed before for (int j = 1; j < animatedAttributes.Length; j++) { string[] attributeLines = animatedAttributes[j].Split('\n'); string attributeNameAndElementLength = attributeLines[0]; string[] nameAndLength = attributeNameAndElementLength.Split(new[] { "##" }, StringSplitOptions.None); string attributeName = nameAndLength[0]; int nKeyframes = int.Parse(nameAndLength[1]); for (int k = 1; k < nKeyframes + 1; k++) { string[] curveProperties = attributeLines[k].Split(new[] { "*#*" }, StringSplitOptions.None); float inTangent = float.Parse(curveProperties[0]), frameValue = float.Parse(curveProperties[1]), outTangent = float.Parse(curveProperties[2]), time = float.Parse(curveProperties[3]); ScalarKeyFrame propKey = new ScalarKeyFrame(inTangent, outTangent, frameValue, time); ScalarFrame propFrame = new ScalarFrame(inTangent, outTangent, frameValue); //check if we have previous entries for a property if (!scalarBlobs[jointName].ContainsKey(attributeName)) { scalarBlobs[jointName].Add(attributeName, new ScalarBlob(attributeName, new SortedList <float, ScalarFrame>())); } scalarBlobs[jointName][attributeName].values.Add(time, propFrame); } } keyframes.Add(jointName, new KeyBlob(scalarBlobs[jointName])); } return(new QAnimation(animationLength, jointNames, hierarchy, keyframes)); }
public void AddChild(QJoint child) { children.Add(child); }
public TransformData GetTransformAt(int jointIdx, float time) { TransformData result = new TransformData(); Vector3 rPosition = new Vector3(); Vector4 rRotation = new Vector4(); Vector3 rScale = new Vector3(); QJoint joint = FindJointByIndex(jointIdx); var JointKeyFrames = keyFrames[joint.name]; foreach (string attribName in JointKeyFrames.keyedAttributes.Keys) { SortedList <float, ScalarFrame> frames = JointKeyFrames.keyedAttributes[attribName].values; int minIdx = BinarySearchLowerBound(frames.Keys, time); float minTime = frames.Keys[minIdx]; float lerpVal = frames[minTime].value; if (minIdx + 1 < frames.Keys.Count) { float minTangent = frames[minTime].outTangent; float maxTime = frames.Keys[minIdx + 1]; float maxVal = frames[maxTime].value; float maxTangent = frames[maxTime].inTangent; lerpVal = CalculateInterpolation(time, minTangent, lerpVal, minTime, maxTangent, maxVal, maxTime); } switch (attribName) { case ("m_LocalPosition.x"): rPosition.x = lerpVal; break; case ("m_LocalPosition.y"): rPosition.y = lerpVal; break; case ("m_LocalPosition.z"): rPosition.z = lerpVal; break; case ("m_LocalRotation.x"): rRotation.x = lerpVal; break; case ("m_LocalRotation.y"): rRotation.y = lerpVal; break; case ("m_LocalRotation.z"): rRotation.z = lerpVal; break; case ("m_LocalRotation.w"): rRotation.w = lerpVal; break; case ("m_LocalScale.x"): rScale.x = lerpVal; break; case ("m_LocalScale.y"): rScale.y = lerpVal; break; case ("m_LocalScale.z"): rScale.z = lerpVal; break; } } result.position = rPosition; rRotation.Normalize(); result.rotation = new Quaternion(rRotation.x, rRotation.y, rRotation.z, rRotation.w); result.scale = rScale; return(result); }