/// <summary> /// Recursively process frame node(s) and their subnodes from an XFileData object /// </summary> /// <param name="node"></param> /// <param name="depth"></param> /// <param name="parentFrame"></param> private static void LoadFrame(XFileData node, int depth, JointFrame parentFrame) { JointFrame newFrame = new JointFrame(node.Name); // Create a new frame // Debug.Write(Depth(depth) + "Creating frame "+newFrame.Name+" ("+newFrame.Type.ToString()+":"+newFrame.Index+") "); if (parentFrame==null) // if there's no parent frame { // the new frame is the root // Debug.WriteLine("as root"); rootFrame = newFrame; } else if (parentFrame.FirstChild==null) // or, if we're the first child { // Debug.WriteLine("as child of "+parentFrame.Name); parentFrame.FirstChild = newFrame; // attach as first child of parent } else // else we're a sibling { JointFrame bigSister = parentFrame.FirstChild; while (bigSister.Sibling!=null) // so scan to the end of this row bigSister = bigSister.Sibling; // Debug.WriteLine("as sibling of "+bigSister.Name); bigSister.Sibling = newFrame; // attach as a sibling } // --------- Recurse through this node's children to construct frame's contents ---------- depth++; for (int i=0; i<node.NumberChildren; i++) { using (XFileData child = node.GetChild(i)) { // **** Frame nested inside this frame if (child.Type==XFileGuid.Frame) { LoadFrame(child, depth, newFrame); } // **** FrameTransformationMatrix else if (child.Type==XFileGuid.FrameTransformMatrix) { LoadTransformationMatrix(child, depth, newFrame); } // **** Mesh else if (child.Type==XFileGuid.Mesh) { string name = child.Name; // use mesh named in xfile if available if (name == "") name = node.Name; // or name it after the frame LoadMesh(child, name, depth, newFrame); } } } }
/// <summary> /// Load an Animation node /// </summary> /// <param name="node"></param> private static void LoadAnimation(XFileData node) { JointFrame frame = null; int f = 0; // Debug.WriteLine("\tReading Animation "+node.Name); // Find the subnode that's a REFERENCE to a frame, then find the frame with that name XFileData frameRef = null; for (f = 0; f < node.NumberChildren; f++) { if (node.GetChild(f).Type == XFileGuid.Frame) { frameRef = node.GetChild(f); break; } } if (frameRef==null) throw new Exception("XFile animation node " + node.Name + "doesn't refer to a frame"); frame = JointFrame.Find(rootFrame, frameRef.Name); if (frame == null) throw new Exception("XFile Animation node " + node.Name + " refers to unknown frame " + frameRef.Name); // If this frame is animatable, create a motion controller and load in the limits. // Non-animatable frames have no motion controller. if (frame.Type==JointFrame.FrameType.Animating) { // Create a motion controller in which to store the limit data motion = new MotionController(); rmin = tmin = smin = false; // We haven't filled any motion members yet // Now iterate through the remaining AnimationKey and AnimationOptions nodes... for (int i=0; i<node.NumberChildren; i++) { using (XFileData child = node.GetChild(i)) { // **** Frame nested inside this frame if (child.Type==XFileGuid.AnimationKey) { LoadKeyframes(child, frame); } // We don't care about AnimationOptions & we skip the frame reference } } // Store the new motion controller in the frame frame.Motion = motion; // Debug.WriteLine("\t\tFrame "+frame.Name+" is animated"); } }
/// <summary> /// Process AnimationSet node(s). /// Each X file should have a SINGLE AnimationSet, containing Animation nodes /// that each contain TWO keyframes (0,1). These define the limits for the /// joint. /// </summary> /// <param name="node"></param> /// <param name="depth"></param> /// <param name="parentFrame"></param> private static void LoadAnimationSet(XFileData node) { // Debug.WriteLine("Reading AnimationSet "+node.Name); // Recurse through the child Animation nodes for this set for (int i=0; i<node.NumberChildren; i++) { using (XFileData child = node.GetChild(i)) { // **** Frame nested inside this frame if (child.Type==XFileGuid.Animation) { LoadAnimation(child); } } } }
/// <summary> /// Recursively create frames and their contents from an XFileData object /// </summary> /// <param name="node"></param> /// <param name="depth"></param> /// <param name="parentFrame"></param> /// <param name="thisFrame"></param> private void LoadDataObject(XFileData node, int depth, SimFrame parentFrame, SimFrame thisFrame) { // --------- handle the instance nodes (references are handled later) ------------ if (node.IsReference==false) { // **** Frame if (node.Type==XFileGuid.Frame) { ReadFrame(node, depth, ref thisFrame); } // **** FrameTransformationMatrix else if (node.Type==XFileGuid.FrameTransformMatrix) { ReadTransformationMatrix(node, depth, thisFrame); } // **** Mesh else if (node.Type==XFileGuid.Mesh) { ReadMesh(node, depth, thisFrame); } // Ignore mesh subset members (materials, normals, etc.) - they're already handled by ReadMesh() // **** Animation set else if (node.Type==XFileGuid.AnimationSet) { ReadAnimationSet(node, depth, thisFrame); } // **** Animation else if (node.Type==XFileGuid.Animation) { } // **** AnimationKey else if (node.Type==XFileGuid.AnimationKey) { } // **** AnimationOptions else if (node.Type==XFileGuid.AnimationOptions) { } // --------- Recurse through this node's children ---------- // Note: we mustn't touch the children of a REFERENCE node or we'll create a duplicate // set of frames, etc. So only run this loop if we've just handled an INSTANCE node for (int i=0; i<node.NumberChildren; i++) { using (XFileData child = node.GetChild(i)) { LoadDataObject(child, depth++, parentFrame, thisFrame); } } } // --------- deal with REFERENCES to existing instances (e.g inside animation nodes) ---------- else { // **** Frame reference if (node.Type==XFileGuid.Frame) { SimFrame refFrame = null; /////rootFrame.Find(node.Name); } } }