/// <summary> /// Process a first-level node from an XFileData object /// </summary> /// <param name="node"></param> /// <param name="depth"></param> /// <param name="parentFrame"></param> /// <param name="thisFrame"></param> private static void LoadRootObject(XFileData node) { // **** Frame if (node.Type==XFileGuid.Frame) { LoadFrame(node, 0, null); } // **** Animation set else if (node.Type==XFileGuid.AnimationSet) { LoadAnimationSet(node); } // TODO: Other root-level objects here }
/// <summary> /// Read a transformation matrix and attach to the current frame /// </summary> /// <param name="node"></param> /// <param name="depth"></param> /// <param name="thisFrame"></param> private static void LoadTransformationMatrix(XFileData node, int depth, JointFrame thisFrame) { try { // Debug.WriteLine(Depth(depth) + "Creating Matrix for "+thisFrame.Name); GraphicsStream stream = node.Lock(); // access the data stream thisFrame.TransformationMatrix = MatrixFromXFile(stream); // read in the matrix node.Unlock(); } catch (Exception e) { Debug.WriteLine("Error reading transformation matrix: "+e.ToString()); throw; } }
/// <summary> /// Read an AnimationKey node and load its transformation into the given frame /// </summary> /// <param name="node"></param> /// <param name="frame"></param> private static void LoadKeyframes(XFileData node, JointFrame frame) { int keyType = 0, keyFrames = 0; int keyTime = 0, keyValues = 0; Quaternion q = new Quaternion(); Vector3 v = new Vector3(); GraphicsStream stream = node.Lock(); // Lock the node and obtain a stream keyType = (int)stream.Read(keyType.GetType()); // get the keyframe type (rotation, etc.) keyFrames = (int)stream.Read(keyFrames.GetType()); // get the number of keyframes (should be 2) if (keyFrames>2) throw new Exception("XFile "+filespec+" should have only two keyframes per animation"); for (int i=0; i<keyFrames; i++) { keyTime = (int)stream.Read(keyTime.GetType()); // time of key (ignored) keyValues = (int)stream.Read(keyValues.GetType()); // number of values in key (ignored) switch (keyType) { // Rotation case 0: q = ReadQuaternion(stream); // get the transformation if (rmin == false) // store it in min or max { motion.RotationMin = q; // (min first, then max if min is full) motion.RotationMax = q; // (fill max too in case no 2nd key) rmin = true; } else motion.RotationMax = q; break; // Translation case 1: v = ReadVector(stream); if (smin == false) { motion.ScaleMin = v; motion.ScaleMax = v; smin = true; } else motion.ScaleMax = v; break; // Scale case 2: v = ReadVector(stream); if (tmin == false) { motion.TranslationMin = v; motion.TranslationMax = v; tmin = true; } else motion.TranslationMax = v; break; } } node.Unlock(); // release the node }
/// <summary> /// Read a mesh and create a Cytoplasm object from it, then attach this to the current frame /// </summary> /// <param name="node"></param> /// <param name="depth"></param> /// <param name="thisFrame"></param> private static void LoadMesh(XFileData node, string name, int depth, JointFrame thisFrame) { // Debug.WriteLine(Depth(depth) + "Creating Mesh "+name+" for "+thisFrame.Name); Mesh mesh = null; ExtendedMaterial[] materials = null; GraphicsStream adjacency = null; EffectInstance[] effects = null; try { mesh = Mesh.FromX(node,MeshFlags.Managed,Engine.Device,out adjacency, out materials, out effects); //Debug.WriteLine(Depth(depth) + "Mesh "+node.Name+" has "+mesh.NumberVertices+" verts and "+materials.Length+" materials"); } catch (Direct3DXException e) { Debug.WriteLine("Error reading mesh: "+e.ToString()); throw; } // Create a Cytoplasm (meshcontainer) object from mesh, materials, etc. // Give it the right name (node.Name) // Link it into the tree of Cytoplasm objects // Link it to this mesh Cytoplasm cyt = new Cytoplasm(folder,name,mesh,materials,effects,adjacency,null); thisFrame.MeshContainer = cyt; }
/// <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 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> /// Read a mesh and create a Cytoplasm object from it, then attach this to the current frame /// </summary> /// <param name="node"></param> /// <param name="depth"></param> /// <param name="thisFrame"></param> private void ReadMesh(XFileData node, int depth, SimFrame thisFrame) { Debug.WriteLine(Depth(depth) + "Creating Mesh "+node.Name+" for "+thisFrame.Name); Mesh mesh = null; ExtendedMaterial[] materials = null; GraphicsStream adjacency = null; EffectInstance[] effects = null; try { mesh = Mesh.FromX(node,MeshFlags.Managed,Engine.Device,out adjacency, out materials, out effects); Debug.WriteLine(Depth(depth) + "Mesh "+node.Name+" has "+mesh.NumberVertices+" verts and "+materials.Length+" materials"); } catch (Direct3DXException e) { Debug.WriteLine("Error reading mesh: "+e.ToString()); throw; } // Create a Cytoplasm (meshcontainer) object from mesh, materials, etc. // Give it the right name (node.Name) // Link it into the tree of Cytoplasm objects // Link it to this mesh // TODO: thisFrame.MeshContainer = CreateCytoplasm( ---stuff---); MeshData md = new MeshData(); // Cytoplasm currently expects a MeshData md.Mesh = mesh; // rather than a simple mesh thisFrame.MeshContainer = new Cytoplasm(node.Name,md,materials,effects,adjacency,null); }
/// <summary> /// Create a new frame from this node /// </summary> /// <param name="node">the XFileData node</param> /// <param name="depth">depth in hierarchy</param> /// <param name="thisFrame">the previous / new current frame</param> private void ReadFrame(XFileData node, int depth, ref SimFrame thisFrame) { SimFrame newFrame = new SimFrame(node.Name); // Create a new frame if (thisFrame==null) // if there's no current frame { // the new frame is the root Debug.WriteLine(Depth(depth) + "Creating frame "+newFrame.Name+" as root"); thisFrame = newFrame; rootFrame = thisFrame; } else if (thisFrame.FirstChild==null) // or, if we're in a new level { Debug.WriteLine(Depth(depth) + "Creating frame "+newFrame.Name+" as child of "+thisFrame.Name); thisFrame.FirstChild = newFrame; // attach as first child of parent thisFrame = newFrame; // and move down a generation } else // else we're a sibling { SimFrame bigSister = thisFrame.FirstChild; while (bigSister.Sibling!=null) // so scan to the end of this row bigSister = bigSister.Sibling; Debug.WriteLine(Depth(depth) + "Creating frame "+newFrame.Name+" as sibling of "+bigSister.Name); bigSister.Sibling = newFrame; // attach as a sibling thisFrame = newFrame; // and start work on the new one } }
private void ReadAnimationSet(XFileData node, int depth, SimFrame thisFrame) { Debug.WriteLine(Depth(depth) + "AnimationSet " + node.Name); }
/// <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); } } }