public void ExportJSON() { string filePath = path + "test_export.json"; RigidNode_Base baseNode = CreateNodeWithChild(); BXDJSkeletonJson.WriteSkeleton(filePath, baseNode); string result = File.ReadAllText(filePath); Assert.Greater(result.Length, 50); }
// TODO: Something weird is going on with the spawn, at least with robots with manipulators. Reset is fine. /// <summary> /// Loads and initializes the physical manipulator object (used in Mix and Match mode) /// </summary> /// <param name="directory">Folder directory of the manipulator</param> /// <param name="robotGameObject">GameObject of the robot the manipulator will be attached to</param> public bool InitializeManipulator(string directory) { ManipulatorObject = new GameObject("Manipulator"); ManipulatorObject.transform.position = robotStartPosition + manipulatorOffset; RigidNode_Base.NODE_FACTORY = delegate(Guid guid) { return(new RigidNode(guid)); }; List <RigidNode_Base> nodes = new List <RigidNode_Base>(); //TO-DO: Read .robot instead (from the new exporters if they are implemented). Maybe need a RobotSkeleton class manipulatorNode = BXDJSkeleton.ReadSkeleton(directory + "\\skeleton.bxdj"); manipulatorNode.ListAllNodes(nodes); //Load node_0 for attaching manipulator to robot RigidNode node = (RigidNode)nodes[0]; node.CreateTransform(ManipulatorObject.transform); if (!node.CreateMesh(directory + "\\" + node.ModelFileName)) { Destroy(ManipulatorObject); return(false); } node.CreateManipulatorJoint(gameObject); node.MainObject.AddComponent <Tracker>().Trace = true; //Load other nodes associated with the manipulator for (int i = 1; i < nodes.Count; i++) { RigidNode otherNode = (RigidNode)nodes[i]; otherNode.CreateTransform(ManipulatorObject.transform); if (!otherNode.CreateMesh(directory + "\\" + otherNode.ModelFileName)) { Destroy(ManipulatorObject); return(false); } otherNode.MainObject.AddComponent <Tracker>().Trace = true; } RootNode.GenerateWheelInfo(); for (int i = 1; i < nodes.Count; i++) { RigidNode otherNode = (RigidNode)nodes[i]; otherNode.CreateJoint(this); } RotateRobot(robotStartOrientation); RobotHasManipulator = true; return(true); }
public void SetNew() { if (SkeletonBase == null || !WarnUnsaved()) { return; } SkeletonBase = null; Meshes = null; ReloadPanels(); }
/// <summary> /// Create a new OGL_RigidNode from existing data /// </summary> /// <remarks> /// This is used primarily for converting another subclass of RigidNode_Base to an OGL_RigidNode. /// For conversion from a RigidNode_Base, casting will suffice. /// </remarks> /// <param name="baseData">The rigid node containing existing model data</param> public OGL_RigidNode(RigidNode_Base baseData) : base(baseData.GUID) { myGUID = SelectManager.AllocateGUID(this); ModelFullID = baseData.ModelFullID; ModelFileName = baseData.ModelFileName; foreach (KeyValuePair <SkeletalJoint_Base, RigidNode_Base> child in baseData.Children) { AddChild(child.Key, new OGL_RigidNode(child.Value)); } }
public static List <BXDAMesh> ExportMeshes(RigidNode_Base baseNode, bool useOCL = false) { SurfaceExporter surfs = new SurfaceExporter(); BXDJSkeleton.SetupFileNames(baseNode); List <RigidNode_Base> nodes = new List <RigidNode_Base>(); baseNode.ListAllNodes(nodes); SynthesisGUI.Instance.ExporterSetMeshes(nodes.Count); List <BXDAMesh> meshes = new List <BXDAMesh>(); foreach (RigidNode_Base node in nodes) { SynthesisGUI.Instance.ExporterSetOverallText("Exporting " + node.ModelFileName); if (node is RigidNode && node.GetModel() != null && node.ModelFileName != null && node.GetModel() is CustomRigidGroup) { Console.WriteLine("Exporting " + node.ModelFileName); try { SynthesisGUI.Instance.ExporterReset(); CustomRigidGroup group = (CustomRigidGroup)node.GetModel(); Console.WriteLine("Exporting meshes..."); BXDAMesh output = surfs.ExportAll(group, node.GUID, (long progress, long total) => { double totalProgress = (((double)progress / (double)total) * 100.0); SynthesisGUI.Instance.ExporterSetSubText(String.Format("Export {1} / {2}", Math.Round(totalProgress, 2), progress, total)); SynthesisGUI.Instance.ExporterSetProgress(totalProgress); }); Console.WriteLine(); Console.WriteLine("Output: " + output.meshes.Count + " meshes"); Console.WriteLine("Computing colliders..."); output.colliders.Clear(); output.colliders.AddRange(ConvexHullCalculator.GetHull(output)); meshes.Add(output); } catch (Exception e) { Console.WriteLine(e.ToString()); throw new Exception("Error exporting mesh: " + node.GetModelID()); } } SynthesisGUI.Instance.ExporterStepOverall(); } return(meshes); }
/// <summary> /// Load a list of nodes into the editor pane /// </summary> /// <param name="root">The base node</param> public void SetSkeleton(RigidNode_Base root) { if (root == null) { nodeList = null; } else { nodeList = root.ListAllNodes(); } UpdateJointList(); }
public JointCardUC(RigidNode_Base node, JointEditorForm jointEditorForm, RobotDataManager robotDataManager) { this.robotDataManager = robotDataManager; this.jointEditorForm = jointEditorForm; this.node = node; InitializeComponent(); WinFormsUtils.DisableScrollSelection(this); AddHighlightAction(this); }
public void TestOdeza() { string odezaPath = @"C:\Users\Victo\AppData\Roaming\Autodesk\Synthesis\Robots\Odesza1\\skeleton.json"; if (!File.Exists(odezaPath)) { return; } RigidNode_Base loaded = BXDJSkeletonJson.ReadSkeleton(odezaPath); Assert.IsNotNull(loaded); }
/// <summary> /// Gets an array of all the exported <see cref="ComponentOccurrence"/>s at and below a node. /// </summary> /// <param name="baseNode"></param> /// <returns></returns> public static ComponentOccurrence[] GetExportedComponents(RigidNode_Base baseNode) { List <ComponentOccurrence> names = new List <ComponentOccurrence>(); foreach (RigidNode_Base node in baseNode.ListAllNodes()) { foreach (string s in node.ModelFullID.Split(new string[] { "-_-" }, StringSplitOptions.RemoveEmptyEntries)) { names.Add(StandardAddInServer.Instance.GetOccurrence(s)); } } return(names.ToArray()); }
private void ExporterWorker_DoWork(object sender, DoWorkEventArgs e) { if (InventorManager.Instance == null) { MessageBox.Show("Couldn't detect a running instance of Inventor."); return; } if (InventorManager.Instance.ActiveDocument == null || !(InventorManager.Instance.ActiveDocument is AssemblyDocument)) { MessageBox.Show("Couldn't detect an open assembly"); return; } InventorManager.Instance.UserInterfaceManager.UserInteractionDisabled = true; RigidNode_Base skeleton = null; try { skeleton = ExportSkeleton(InventorManager.Instance.ComponentOccurrences.OfType <ComponentOccurrence>().ToList()); } catch (Exporter.EmptyAssemblyException) { SetProgressWindowVisisble(false); string caption = "Empty Assembly"; MessageBoxButtons buttons = MessageBoxButtons.OK; DialogResult r = MessageBox.Show("Assembly has no parts to export.", caption, buttons); } catch (Exporter.InvalidJointException ex) { SetProgressWindowVisisble(false); string caption = "Invalid Joint"; MessageBoxButtons buttons = MessageBoxButtons.OK; DialogResult r = MessageBox.Show(ex.Message, caption, buttons); } catch (Exporter.NoGroundException) { SetProgressWindowVisisble(false); string caption = "No Ground"; MessageBoxButtons buttons = MessageBoxButtons.OK; DialogResult r = MessageBox.Show("Please ground a part in your assembly to export your robot.", caption, buttons); } finally { SynthesisGUI.Instance.SkeletonBase = skeleton; } }
/// <summary> /// Reads the skeleton contained in the XML BXDJ file specified and /// returns the corresponding RigidNode_Base. /// </summary> /// <param name="path"></param> /// <param name="useValidation"></param> private static RigidNode_Base ReadSkeleton_4_0(string path, bool useValidation = true) { RigidNode_Base root = null; List <RigidNode_Base> nodes = new List <RigidNode_Base>(); XmlReaderSettings settings = new XmlReaderSettings(); if (useValidation)// if the schema should be validated, then run the BXDJ against the schema to make sure all the value are there, oftentimes robot instace invalid issues are found here { settings.Schemas.Add(XmlSchema.Read(new StringReader(BXDJ_XSD_4_0), null)); settings.ValidationType = ValidationType.Schema; } else { settings.ValidationType = ValidationType.None; } XmlReader reader = XmlReader.Create(path, settings); try { foreach (string name in IOUtilities.AllElements(reader)) // iterates over all the top level data { switch (name) // handles reading the different XML tags { case "DriveTrainType": // Reads the current element as a drive train type. root.driveTrainType = (RigidNode_Base.DriveTrainType)Enum.Parse(typeof(RigidNode_Base.DriveTrainType), reader.ReadElementContentAsString()); break; case "Node": // Reads the current element as a node. ReadNode_4_0(reader.ReadSubtree(), nodes, ref root); break; } } } catch (Exception)// A variety of exceptions can take place if the file is invalid, but we will always want to return null. { // If the file is invalid, return null. return(null); } finally { // Closes the reader. reader.Close(); } return(nodes[0]);// returns the base node of the skeleton }
/// <summary> /// Ensures that every node is assigned a model file name by assigning all nodes without a file name a generated name. /// </summary> /// <param name="baseNode">The base node of the skeleton</param> /// <param name="overwrite">Overwrite existing</param> public static void SetupFileNames(RigidNode_Base baseNode) { List <RigidNode_Base> nodes = new List <RigidNode_Base>(); baseNode.ListAllNodes(nodes); for (int i = 0; i < nodes.Count; i++) { if (nodes[i].ModelFileName == null) { nodes[i].ModelFileName = ("node_" + i + ".bxda"); } } }
/// <summary> /// Adds a panel to <see cref="MassPanel"/> /// </summary> /// <param name="name"></param> /// <param name="node"></param> private void AddPanelRow(string name, RigidNode_Base node) { MassDataRow row = new MassDataRow(name, node); row.Width = MassPanel.Width - 17; row.Location = new Point(0, 20 * MassPanel.Controls.Count); row.MassChanged += delegate(decimal amount) { totalMass += (float)amount; UpdateMassCount(); }; MassPanel.Controls.Add(row); }
/// <summary> /// Open a previously exported robot. /// </summary> /// <param name="validate">If it is not null, this will validate the open inventor assembly.</param> public void OpenExisting() { if (SkeletonBase != null && !WarnUnsaved()) { return; } string dirPath = OpenFolderPath(); if (dirPath == null) { return; } try { List <RigidNode_Base> nodes = new List <RigidNode_Base>(); SkeletonBase = BXDJSkeleton.ReadSkeleton(dirPath + "\\skeleton.bxdj"); SkeletonBase.ListAllNodes(nodes); Meshes = new List <BXDAMesh>(); foreach (RigidNode_Base n in nodes) { BXDAMesh mesh = new BXDAMesh(); mesh.ReadFromFile(dirPath + "\\" + n.ModelFileName); if (!n.GUID.Equals(mesh.GUID)) { MessageBox.Show(n.ModelFileName + " has been modified.", "Could not load mesh."); return; } Meshes.Add(mesh); } for (int i = 0; i < Meshes.Count; i++) { ((OGL_RigidNode)nodes[i]).loadMeshes(Meshes[i]); } } catch (Exception e) { MessageBox.Show(e.ToString()); } ReloadPanels(); }
/// <summary> /// Reads the skeleton contained in the XML BXDJ file specified and /// returns the corresponding RigidNode_Base. /// </summary> /// <param name="path"></param> /// <param name="useValidation"></param> private static RigidNode_Base ReadSkeleton_5_0(string path, bool useValidation = true) { RigidNode_Base root = null; List <RigidNode_Base> nodes = new List <RigidNode_Base>(); XmlReaderSettings settings = new XmlReaderSettings(); if (useValidation) { settings.Schemas.Add(XmlSchema.Read(new StringReader(BXDJ_XSD_5_0), null)); settings.ValidationType = ValidationType.Schema; } else { settings.ValidationType = ValidationType.None; } XmlReader reader = XmlReader.Create(path, settings); try { foreach (string name in IOUtilities.AllElements(reader)) { switch (name) { case "DriveTrainType": ReadNode_5_0(reader.ReadSubtree(), nodes, ref root); break; case "Node": // Reads the current element as a node. ReadNode_5_0(reader.ReadSubtree(), nodes, ref root); break; } } } catch (Exception)// A variety of exceptions can take place if the file is invalid, but we will always want to return null. { // If the file is invalid, return null. return(null); } finally { // Closes the reader. reader.Close(); } return(nodes[0]); }
public void AddNode(RigidNode_Base node) { if (listViewNodes.Items.Cast <ListViewItem>().FirstOrDefault(i => i.Tag != null && ((RigidNode_Base)i.Tag).GetModelID() == node.GetModelID()) != null) { return; } ListViewItem item = new ListViewItem(new string[] { (node.GetParent() != null) ? node.GetParent().ModelFileName : "N/A", node.ModelFileName, "False", "False", "False" }); item.Tag = node; listViewNodes.Items.Add(item); nodes.Add(node); }
/// <summary> /// Fills the slot with a new <see cref="WheelSetupPanel"/> and sets its <see cref="WizardData.WizardWheelType"/> properly to <paramref name="wheelType"/> /// </summary> /// <param name="node"></param> /// <param name="wheelType"></param> public void FillSlot(RigidNode_Base node, WizardData.WizardWheelType wheelType = WizardData.WizardWheelType.NORMAL) { wheelSetupPanel = new WheelSetupPanel(node, wheelType); wheelSetupPanel.Dock = DockStyle.Fill; this.SuspendLayout(); while (Controls.Count > 0) { Controls[0].Dispose(); } this.Controls.Add(wheelSetupPanel); wheelSetupPanel.Visible = true; this.ResumeLayout(); wheelSetupPanel._WheelTypeChangedInternal += delegate() { OnWheelTypeChanged(); }; IsFilled = true; }
/// <summary> /// Sorts all the wheels into left and right. /// </summary> /// <param name="nodes"></param> /// <param name="IsHDrive"></param> /// <returns></returns> public static RigidNode_Base[][] SortWheels(List <RigidNode_Base> nodes, bool IsHDrive = false) { if (!IsHDrive) { Dictionary <GUIDDoublePair, RigidNode_Base> nodeDict = new Dictionary <GUIDDoublePair, RigidNode_Base>(); foreach (var node in nodes) { nodeDict.Add(new GUIDDoublePair { guid = Guid.NewGuid(), d = node.GetSkeletalJoint().GetAngularDOF().First().basePoint.x }, node); } List <GUIDDoublePair> newKeyOrder = nodeDict.Keys.OrderBy(x => x.d).ToList(); RigidNode_Base[] left = new RigidNode_Base[nodes.Count / 2]; RigidNode_Base[] right = new RigidNode_Base[nodes.Count / 2]; string leftNodes = "Left Nodes: ", rightNodes = "Right Nodes: "; int i = 0; foreach (GUIDDoublePair key in newKeyOrder) { if (i < nodes.Count / 2) { left[i] = nodeDict[key]; leftNodes += nodeDict[key].ModelFileName + ", "; } else { right[i - (nodes.Count / 2)] = nodeDict[key]; rightNodes += nodeDict[key].ModelFileName + ", "; } i++; } #region DEBUG #if DEBUG MessageBox.Show(leftNodes.Substring(0, leftNodes.Length - 2) + "\n" + rightNodes.Substring(0, rightNodes.Length - 2)); #endif #endregion return(new RigidNode_Base[][] { left, right }); } else { return(null); } }
public static RigidNode_Base ReadSkeletonSafe(string path) { string jsonPath = path + ".json"; string xmlPath = path + ".bxdj"; RigidNode_Base node = null; if (File.Exists(jsonPath)) { //Load JSON Debug.Log("Loading JSON robot: " + jsonPath); node = BXDJSkeletonJson.ReadSkeleton(jsonPath); } else { node = BXDJSkeleton.ReadSkeleton(xmlPath); } return(node); }
public static RigidNode_Base ReadSkeleton(string path) { string jsonData = File.ReadAllText(path); RigidNode_Base root = null; JsonConverter[] converters = { new JointConverter(), new DriverMetaConverter() }; JsonSkeleton skeleton = JsonConvert.DeserializeObject <JsonSkeleton>(jsonData, new JsonSerializerSettings() { Converters = converters }); List <JsonSkeletonNode> nodes = skeleton.Nodes; if (nodes.Count < 1) { Console.Error.WriteLine("0 Nodes Loaded! Failed import"); return(null); } foreach (JsonSkeletonNode node in nodes) { RigidNode_Base newNode = RigidNode_Base.NODE_FACTORY(new Guid(node.GUID)); newNode.ModelFileName = node.ModelFileName; newNode.ModelFullID = node.ModelID; if (node.ParentID == "-1") { root = newNode; root.driveTrainType = skeleton.DriveTrainType; } else { root.AddChild(node.joint, newNode); } } return(root); }
/// <summary> /// The lite equivalent of the 'Start Exporter' <see cref="Button"/> in the <see cref="ExporterForm"/>. Used in <see cref="ExporterWorker_DoWork(Object, "/> /// </summary> /// <seealso cref="ExporterWorker_DoWork"/> /// <param name="baseNode"></param> /// <returns></returns> public List <BXDAMesh> ExportMeshesLite(RigidNode_Base baseNode) { SurfaceExporter surfs = new SurfaceExporter(); BXDJSkeleton.SetupFileNames(baseNode, true); List <RigidNode_Base> nodes = new List <RigidNode_Base>(); baseNode.ListAllNodes(nodes); List <BXDAMesh> meshes = new List <BXDAMesh>(); foreach (RigidNode_Base node in nodes) { SetProgressText("Exporting " + node.ModelFileName); if (node is RigidNode && node.GetModel() != null && node.ModelFileName != null && node.GetModel() is CustomRigidGroup) { try { CustomRigidGroup group = (CustomRigidGroup)node.GetModel(); surfs.Reset(node.GUID); surfs.ExportAll(group, (long progress, long total) => { SetProgressText(String.Format("Export {0} / {1}", progress, total)); }); BXDAMesh output = surfs.GetOutput(); output.colliders.Clear(); output.colliders.AddRange(ConvexHullCalculator.GetHull(output)); meshes.Add(output); } catch (Exception e) { throw new Exception("Error exporting mesh: " + node.GetModelID(), e); } } } return(meshes); }
/// <summary> /// The <see cref="JointEditorEvent"/> to open up a <see cref="SensorListForm"/> /// </summary> /// <param name="node">The node connected to the joint to edit the sensors on</param> private void ListSensors_Internal(List <RigidNode_Base> nodes) { if (nodes == null || nodes.Count != 1) { return; } RigidNode_Base node = nodes[0]; if (node == null) { return; } currentlyEditing = true; SensorListForm listForm = new SensorListForm(node.GetSkeletalJoint()); listForm.ShowDialog(ParentForm); ModifiedJoint?.Invoke(nodes); this.UpdateJointList(); currentlyEditing = false; }
public void AddSelection(RigidNode_Base node, bool clearExisting) { if (rootNode == null) { return; } foreach (BXDAEditorNode treeNode in rootNode.Nodes) { treeNode.BackColor = Color.White; } if (node == null) { treeView1.SelectedNode = null; return; } treeView1.SelectedNode = rootNode.Nodes.OfType <BXDAEditorNode>().FirstOrDefault(treeNode => treeNode.data[0] is BXDAMesh && treeNode.data[0] == ((OGLViewer.OGL_RigidNode)node).baseMesh); }
/// <summary> /// Build the node tree of the robot from Inventor /// </summary> public bool LoadRobotSkeleton(Progress <ProgressUpdate> progress = null) { try { RobotBaseNode = SkeletonBuilder.ExportSkeleton(progress); GC.Collect(); } catch (InvalidComObjectException) // TODO: Don't do this { } catch (TaskCanceledException) { return(false); } catch (Exception e) { MessageBox.Show(e.Message); return(false); } return(RobotBaseNode != null); }
/// <summary> /// Checks if a baseNode matches up with the assembly. Passed as a <see cref="ValidationAction"/> to /// </summary> /// <param name="baseNode"></param> /// <param name="message"></param> /// <returns></returns> private static bool ValidateAssembly(RigidNode_Base baseNode, out string message) { var validationCount = 0; var failedCount = 0; var nodes = baseNode.ListAllNodes(); foreach (var node in nodes) { var failedValidation = false; foreach (var componentName in node.ModelFullID.Split(new string[] { "-_-" }, StringSplitOptions.RemoveEmptyEntries)) { if (!CheckForOccurrence(componentName)) { failedCount++; failedValidation = true; } } if (!failedValidation) { validationCount++; } } if (validationCount == nodes.Count) { message = String.Format("The assembly validated successfully. {0} / {1} nodes checked out.", validationCount, nodes.Count); return(true); } else { message = String.Format( "The assembly failed to validate. {0} / {1} nodes checked out. {2} parts/assemblies were not found.", validationCount, nodes.Count, failedCount); return(false); } }
private void listViewNodes_MouseDoubleClick(object sender, MouseEventArgs e) { System.Drawing.Point clientPoint = e.Location; ListViewItem item = listViewNodes.GetItemAt(clientPoint.X, clientPoint.Y); if (item != null) { ListViewItem.ListViewSubItem subItem = item.GetSubItemAt(clientPoint.X, clientPoint.Y); if (subItem != null && item.SubItems.IndexOf(subItem) >= 2) { subItem.Text = (subItem.Text == "False") ? "True" : "False"; } RigidNode_Base node = (RigidNode_Base)item.Tag; CustomRigidGroup group = (CustomRigidGroup)node.GetModel(); ExporterHint newHint; newHint.Convex = item.SubItems[2].Text == "False"; newHint.MultiColor = item.SubItems[3].Text == "True"; newHint.HighResolution = item.SubItems[4].Text == "True"; group.hint = newHint; } }
private void listViewNodes_MouseDoubleClick(object sender, MouseEventArgs e) { foreach (RigidNode_Base node in nodes) { Debug.WriteLine("Model Full Name: " + node.ModelFileName + "\nModel Full ID: " + node.ModelFullID); } System.Drawing.Point clientPoint = e.Location; ListViewItem item = listViewNodes.GetItemAt(clientPoint.X, clientPoint.Y); if (item != null) { ListViewItem.ListViewSubItem subItem = item.GetSubItemAt(clientPoint.X, clientPoint.Y); if (subItem != null && item.SubItems.IndexOf(subItem) >= 2) { subItem.Text = (subItem.Text == "False") ? "True" : "False"; } RigidNode_Base node = (RigidNode_Base)item.Tag; CustomRigidGroup group = (CustomRigidGroup)node.GetModel(); } }
public void AddSelection(RigidNode_Base node, bool clearActive) { if (clearActive) { lstJoints.SelectedItems.Clear(); } foreach (ListViewItem listItem in lstJoints.Items.OfType <ListViewItem>()) { if (!lstJoints.SelectedItems.Contains(listItem)) { listItem.BackColor = Control.DefaultBackColor; } } ListViewItem item = lstJoints.Items.OfType <ListViewItem>().FirstOrDefault(i => i.Tag == node); if (item != null) { item.BackColor = System.Drawing.Color.LightSteelBlue; item.Selected = true; item.Focused = true; } }
public void ReadJSON() { string filePath = path + "test_export.json"; RigidNode_Base toCreate = CreateNodeWithChild(); BXDJSkeletonJson.WriteSkeleton(filePath, toCreate); RigidNode_Base created = BXDJSkeletonJson.ReadSkeleton(filePath); Assert.AreEqual(toCreate.GUID, created.GUID); Assert.AreEqual(toCreate.Children.Count, created.Children.Count); SkeletalJoint_Base firstJointtoCreate = toCreate.Children.Keys.First <SkeletalJoint_Base>(); SkeletalJoint_Base firstJointCreated = created.Children.Keys.First <SkeletalJoint_Base>(); Assert.AreEqual( toCreate.Children[firstJointtoCreate].GetSkeletalJoint().GetJointType(), created.Children[firstJointCreated].GetSkeletalJoint().GetJointType() ); }
private void StandaloneViewerForm_Shown(object sender, EventArgs e) { RigidNode_Base node = BXDJSkeleton.ReadSkeleton(LaunchParams.Path + @"\skeleton.bxdj"); List <RigidNode_Base> nodes = node.ListAllNodes(); List <BXDAMesh> meshes = new List <BXDAMesh>(); foreach (RigidNode_Base n in nodes) { BXDAMesh mesh = new BXDAMesh(); mesh.ReadFromFile(LaunchParams.Path + "\\" + n.ModelFileName); if (!n.GUID.Equals(mesh.GUID)) { MessageBox.Show(n.ModelFileName + " has been modified.", "Could not load mesh."); } meshes.Add(mesh); } robotViewer1.LoadModel(node, meshes); robotViewer1.FixLimits(); robotViewer1.HighlightAll(); }