/// <summary>
    /// Exports all the components in this group to the in-RAM mesh.
    /// </summary>
    /// <param name="group">Group to export from</param>
    /// <param name="reporter">Progress reporter</param>
    public BXDAMesh ExportAll(CustomRigidGroup group, Guid guid, BXDIO.ProgressReporter reporter = null)
    {
        // Create output mesh
        MeshController outputMesh = new MeshController(guid);

        // Collect surfaces to export
        List <SurfaceBody> plannedSurfaces = GenerateExportList(group, outputMesh.Mesh.physics);

        // Export faces, multithreaded
        if (plannedSurfaces.Count > 0)
        {
            // Reset progress bar
            reporter?.Invoke(0, plannedSurfaces.Count);

            // Start jobs
            int    totalJobsFinished = 0;
            object finishLock        = new object(); // Used to prevent multiple threads from updating progress bar at the same time.

            Parallel.ForEach(plannedSurfaces, (SurfaceBody surface) =>
            {
                CalculateSurfaceFacets(surface, outputMesh, SynthesisGUI.PluginSettings.GeneralUseFancyColors);

                lock (finishLock)
                {
                    totalJobsFinished++;
                    reporter?.Invoke(totalJobsFinished, plannedSurfaces.Count);
                }
            });

            outputMesh.DumpOutput();
        }

        return(outputMesh.Mesh);
    }
    //private FindPartMatches

    public RotationalJoint(CustomRigidGroup parent, CustomRigidJoint rigidJoint)
    {
        if (!(IsRotationalJoint(rigidJoint)))
        {
            throw new Exception("Not a rotational joint");
        }
        wrapped = new SkeletalJoint(parent, rigidJoint);

        try
        {
            axis      = Utilities.ToBXDVector(rigidJoint.geomOne.Normal);
            basePoint = Utilities.ToBXDVector(rigidJoint.geomOne.Center);
        }
        catch
        {
            axis      = Utilities.ToBXDVector(rigidJoint.geomOne.Direction);
            basePoint = Utilities.ToBXDVector(rigidJoint.geomOne.RootPoint);
        }


        hasAngularLimit = wrapped.asmJoint.HasAngularPositionLimits;
        if ((hasAngularLimit))
        {
            angularLimitLow  = (float)wrapped.asmJoint.AngularPositionStartLimit.Value;
            angularLimitHigh = (float)wrapped.asmJoint.AngularPositionEndLimit.Value;
        }
        currentAngularPosition = !((wrapped.asmJoint.AngularPosition == null)) ? (float)wrapped.asmJoint.AngularPosition.Value : 0;
    }
Beispiel #3
0
    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();
            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;
        }
    }
Beispiel #4
0
    public LinearJoint(CustomRigidGroup parent, CustomRigidJoint rigidJoint)
    {
        Console.WriteLine(rigidJoint);
        if (!(IsLinearJoint(rigidJoint)))
        {
            throw new Exception("Not a linear joint");
        }
        wrapped = new SkeletalJoint(parent, rigidJoint);

        if (wrapped.childGroup == rigidJoint.groupOne)
        {
            axis      = Utilities.ToBXDVector(rigidJoint.geomTwo.Direction);
            basePoint = Utilities.ToBXDVector(rigidJoint.geomTwo.RootPoint);
        }
        else
        {
            axis      = Utilities.ToBXDVector(rigidJoint.geomOne.Direction);
            basePoint = Utilities.ToBXDVector(rigidJoint.geomOne.RootPoint);
        }

        if ((hasUpperLimit = wrapped.asmJoint.HasLinearPositionEndLimit) && (hasLowerLimit = wrapped.asmJoint.HasLinearPositionStartLimit))
        {
            linearLimitHigh = (float)wrapped.asmJoint.LinearPositionEndLimit.Value;
            linearLimitLow  = (float)wrapped.asmJoint.LinearPositionStartLimit.Value;
        }
        else
        {
            throw new Exception("Joints with linear motion need two limits.");
        }
        currentLinearPosition = !((wrapped.asmJoint.LinearPosition == null)) ? ((float)wrapped.asmJoint.LinearPosition.Value) : 0;
    }
Beispiel #5
0
    /// <summary>
    /// Adds the mesh for all the components and their subcomponenets in the custom rigid group.  <see cref="ExportAll(ComponentOccurrence,bool,bool,bool)"/>
    /// </summary>
    /// <param name="group">The group to export from</param>
    /// <param name="mesh">Mesh to store physics data in.</param>
    /// <returns>All the sufaces to export</returns>
    private List <SurfaceBody> GenerateExportList(CustomRigidGroup group, PhysicalProperties physics)
    {
        List <SurfaceBody> plannedExports = new List <SurfaceBody>();

        // Calculate minimum volume to export a component
        double maxVolume = 0;

        foreach (ComponentOccurrence occ in group.occurrences)
        {
            double curVolume = Utilities.BoxVolume(occ.RangeBox);
            if (curVolume > maxVolume)
            {
                maxVolume = curVolume;
            }
        }
        double minVolume = maxVolume * MIN_VOLUME_PERCENT;

        // Analyze all component occurrences
        foreach (ComponentOccurrence occ in group.occurrences)
        {
            if (Utilities.BoxVolume(occ.RangeBox) >= minVolume)
            {
                GenerateExportList(occ, plannedExports, physics, minVolume);
            }
        }

        return(plannedExports);
    }
Beispiel #6
0
        // public bool childIsTheOne;


        public SkeletalJoint(CustomRigidGroup parent, CustomRigidJoint rigidJoint)
        {
            if (rigidJoint.joints.Count != 1)
            {
                throw new Exception("Not a proper joint");
            }

            asmJoint           = rigidJoint.joints[0].Definition;
            asmJointOccurrence = rigidJoint.joints[0];
            childGroup         = null;
            parentGroup        = parent;
            this.rigidJoint    = rigidJoint;
            if (rigidJoint.groupOne.Equals(parent))
            {
                childGroup = rigidJoint.groupTwo;
            }
            else if (rigidJoint.groupTwo.Equals(parent))
            {
                childGroup = rigidJoint.groupOne;
            }
            else
            {
                throw new Exception("Couldn't match parent group");
            }
            if (childGroup == null)
            {
                throw new Exception("Not a proper joint: No child joint found");
            }

            /*childIsTheOne = childGroup.Contains(asmJointOccurrence.AffectedOccurrenceOne);
             * if (!childIsTheOne && !childGroup.Contains(asmJointOccurrence.AffectedOccurrenceTwo))
             * {
             * throw new Exception("Expected child not found inside assembly joint.");
             * }*/
        }
 /// <summary>
 /// Grabs the joints and groups from the Inventor results,
 /// </summary>
 /// <param name="results"></param>
 public CustomRigidResults(RigidBodyResults results)
 {
     Console.WriteLine("Building custom dataset");
     groups = new List <CustomRigidGroup>(results.RigidBodyGroups.Count);
     joints = new List <CustomRigidJoint>(results.RigidBodyJoints.Count);
     foreach (RigidBodyGroup group in results.RigidBodyGroups)
     {
         CustomRigidGroup tmp = new CustomRigidGroup(group);
         if ((!(groupIDToCustom.ContainsKey(tmp.fullQualifier))))
         {
             groups.Add(tmp);
             groupIDToCustom.Add(tmp.fullQualifier, tmp);
         }
         else
         {
             Console.WriteLine("GroupID Collision: " + groupIDToCustom[CustomRigidGroup.GetGroupQualifier(group)].ToString() + " and " + tmp.ToString());
         }
         Console.Write("Group " + groups.Count + "/" + results.RigidBodyGroups.Count + "\tJoint " + joints.Count + "/" + results.RigidBodyJoints.Count);
     }
     foreach (RigidBodyJoint joint in results.RigidBodyJoints)
     {
         joints.Add(new CustomRigidJoint(joint, groupIDToCustom[CustomRigidGroup.GetGroupQualifier(joint.GroupOne)], groupIDToCustom[CustomRigidGroup.GetGroupQualifier(joint.GroupTwo)]));
         Console.Write("Group " + groups.Count + "/" + results.RigidBodyGroups.Count + "\tJoint " + joints.Count + "/" + results.RigidBodyJoints.Count);
     }
     Console.WriteLine();
     Console.WriteLine("Built custom dataset");
     RigidBodyCleaner.CleanMeaningless(this);
 }
Beispiel #8
0
    public CylindricalJoint(CustomRigidGroup parent, CustomRigidJoint rigidJoint)
    {
        if (!(IsCylindricalJoint(rigidJoint)))
        {
            throw new Exception("Not a Cylindrical joint");
        }
        wrapped = new SkeletalJoint(parent, rigidJoint);

        ReloadInventorJoint();
    }
Beispiel #9
0
    public BallJoint(CustomRigidGroup parent, CustomRigidJoint rigidJoint)
    {
        if (!(IsBallJoint(rigidJoint)))
        {
            throw new Exception("Not a rotational joint");
        }
        wrapped = new SkeletalJoint(parent, rigidJoint);

        basePoint = Utilities.ToBXDVector(rigidJoint.geomOne);
    }
Beispiel #10
0
    public PlanarJoint(CustomRigidGroup parent, CustomRigidJoint rigidJoint)
    {
        if (!(IsPlanarJoint(rigidJoint)))
        {
            throw new Exception("Not a planar joint");
        }
        wrapped = new SkeletalJoint(parent, rigidJoint);

        ReloadInventorJoint();
    }
Beispiel #11
0
    public static List <BXDAMesh> ExportMeshes(RigidNode_Base baseNode, bool useOCL = false)
    {
        SurfaceExporter surfs = new SurfaceExporter();

        BXDJSkeleton.SetupFileNames(baseNode, true);

        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();
                    surfs.Reset(node.GUID);
                    Console.WriteLine("Exporting meshes...");
                    surfs.ExportAll(group, (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();
                    BXDAMesh output = surfs.GetOutput();
                    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);
    }
Beispiel #12
0
    public LinearJoint(CustomRigidGroup parent, CustomRigidJoint rigidJoint)
    {
        Console.WriteLine(rigidJoint);
        if (!(IsLinearJoint(rigidJoint)))
        {
            throw new Exception("Not a linear joint");
        }
        wrapped = new SkeletalJoint(parent, rigidJoint);

        ReloadInventorJoint();
    }
    /// <summary>
    /// Exports all the components in this group to the in-RAM mesh.
    /// </summary>
    /// <param name="group">Group to export from</param>
    /// <param name="reporter">Progress reporter</param>
    public void ExportAll(CustomRigidGroup group, BXDIO.ProgressReporter reporter = null)
    {
#if LITEMODE
        LiteExporterForm.Instance.SetProgressText("Including parts...");
#else
        SynthesisGUI.Instance.ExporterSetSubText("Including parts");
#endif

        List <ExportPlan> plans = GenerateExportList(group);
        Console.WriteLine();
        reporter?.Invoke(0, plans.Count);
        for (int i = 0; i < plans.Count; i++)
        {
            AddFacets(plans[i].surf, plans[i].bestResolution, plans[i].separateFaces);
            reporter?.Invoke((i + 1), plans.Count);
        }
    }
Beispiel #14
0
    public CylindricalJoint(CustomRigidGroup parent, CustomRigidJoint rigidJoint)
    {
        if (!(IsCylindricalJoint(rigidJoint)))
        {
            throw new Exception("Not a Cylindrical joint");
        }
        wrapped = new SkeletalJoint(parent, rigidJoint);

        if (wrapped.childGroup == rigidJoint.groupOne)
        {
            axis      = Utilities.ToBXDVector(rigidJoint.geomTwo.Direction);
            basePoint = Utilities.ToBXDVector(rigidJoint.geomTwo.RootPoint);
        }
        else
        {
            axis      = Utilities.ToBXDVector(rigidJoint.geomOne.Direction);
            basePoint = Utilities.ToBXDVector(rigidJoint.geomOne.RootPoint);
        }

        currentLinearPosition = wrapped.asmJoint.LinearPosition != null ? (float)wrapped.asmJoint.LinearPosition.Value : 0;

        hasAngularLimit = wrapped.asmJoint.HasAngularPositionLimits;
        if (hasAngularLimit)
        {
            angularLimitLow  = (float)wrapped.asmJoint.AngularPositionStartLimit.Value;
            angularLimitHigh = (float)wrapped.asmJoint.AngularPositionEndLimit.Value;
        }
        currentAngularPosition = wrapped.asmJoint.AngularPosition != null ? (float)wrapped.asmJoint.AngularPosition.Value : 0;

        hasLinearStartLimit = wrapped.asmJoint.HasLinearPositionStartLimit;
        hasLinearEndLimit   = wrapped.asmJoint.HasLinearPositionEndLimit;

        if (hasLinearStartLimit && hasLinearEndLimit)
        {
            linearLimitStart = (float)wrapped.asmJoint.LinearPositionStartLimit.Value;
            linearLimitEnd   = (float)wrapped.asmJoint.LinearPositionEndLimit.Value;
        }
        else
        {
            throw new Exception("Joints with linear motion need two limits.");
        }
        wrapped.asmJoint.LinearPosition = wrapped.asmJoint.LinearPosition;
    }
Beispiel #15
0
    /// <summary>
    /// Exports all the components in this group to the in-RAM mesh.
    /// </summary>
    /// <param name="group">Group to export from</param>
    /// <param name="reporter">Progress reporter</param>
    public void ExportAll(CustomRigidGroup group, BXDIO.ProgressReporter reporter = null)
    {
        SynthesisGUI.Instance.ExporterSetSubText("Including parts");

        List <ExportPlan> plans = GenerateExportList(group);

        Console.WriteLine();
        if (reporter != null)
        {
            reporter(0, plans.Count);
        }
        for (int i = 0; i < plans.Count; i++)
        {
            AddFacets(plans[i].surf, plans[i].bestResolution, plans[i].separateFaces);
            if (reporter != null)
            {
                reporter((i + 1), plans.Count);
            }
        }
    }
    public PlanarJoint(CustomRigidGroup parent, CustomRigidJoint rigidJoint)
    {
        if (!(IsPlanarJoint(rigidJoint)))
        {
            throw new Exception("Not a planar joint");
        }
        wrapped = new SkeletalJoint(parent, rigidJoint);


        if (wrapped.childGroup == rigidJoint.groupOne)
        {
            normal    = Utilities.ToBXDVector(rigidJoint.geomTwo.Normal);
            basePoint = Utilities.ToBXDVector(rigidJoint.geomTwo.RootPoint);
        }
        else
        {
            normal    = Utilities.ToBXDVector(rigidJoint.geomOne.Normal);
            basePoint = Utilities.ToBXDVector(rigidJoint.geomOne.RootPoint);
        }
    }
Beispiel #17
0
    /// <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);
    }
Beispiel #18
0
    /// <summary>
    /// Merges all the grounded bodies within the given rigid results into a single group.
    /// </summary>
    /// <remarks>
    /// This also updates the references of all the rigid joints to the new groups.
    /// </remarks>
    /// <exception cref="InvalidOperationException">No grounded bodies exist to merge.</exception>
    /// <param name="results">Rigid results to clean</param>
    public static void CleanGroundedBodies(CustomRigidResults results)
    {
        CustomRigidGroup firstRoot = null;

        //Bundles all the grounded components together into one CustomRigidGroup.
        foreach (CustomRigidGroup group in results.groups)
        {
            if (group.grounded)
            {
                if ((firstRoot == null))
                {
                    firstRoot = group;
                }
                else
                {
                    firstRoot.occurrences.AddRange(group.occurrences);
                    group.occurrences.Clear();
                }
            }
        }
        if (firstRoot != null)
        {
            foreach (CustomRigidJoint joint in results.joints)
            {
                //If a group has no occurrences, its because they were transferred to the firstRoot group.  Updates joints to attach to that joint.
                if (joint.groupOne.occurrences.Count == 0)
                {
                    joint.groupOne = firstRoot;
                }
                if (joint.groupTwo.occurrences.Count == 0)
                {
                    joint.groupTwo = firstRoot;
                }
            }
        }
        else
        {
            throw new Exporter.NoGroundException();
        }
        CleanMeaningless(results);
    }
    /// <summary>
    /// Adds the mesh for all the components and their subcomponenets in the custom rigid group.  <see cref="ExportAll(ComponentOccurrence,bool,bool,bool)"/>
    /// </summary>
    /// <remarks>
    /// This uses the best resolution and separate faces options stored inside the provided custom rigid group.
    /// </remarks>
    /// <param name="group">The group to export from</param>
    /// <returns>All the sufaces to export</returns>
    private List <ExportPlan> GenerateExportList(CustomRigidGroup group)
    {
        List <ExportPlan> plannedExports = new List <ExportPlan>();

        double totalVolume = 0;

        foreach (ComponentOccurrence occ in group.occurrences)
        {
            totalVolume += Utilities.BoxVolume(occ.RangeBox);
        }
        totalVolume /= group.occurrences.Count * adaptiveDegredation;

        foreach (ComponentOccurrence occ in group.occurrences)
        {
            if (!adaptiveIgnoring || Utilities.BoxVolume(occ.RangeBox) >= totalVolume)
            {
                plannedExports.AddRange(GenerateExportList(occ, group.hint.HighResolution, group.hint.MultiColor));
            }
        }
        return(plannedExports);
    }
Beispiel #20
0
        /// <summary>
        /// Exports all the components in this group to the in-RAM mesh.
        /// </summary>
        /// <param name="group">Group to export from</param>
        /// <param name="guid"></param>
        /// <param name="reporter">Progress reporter</param>
        /// <param name="backgroundWorker"></param>
        public BXDAMesh ExportAll(CustomRigidGroup @group, Guid guid, BXDIO.ProgressReporter reporter = null, BackgroundWorker backgroundWorker = null)
        {
            // Create output mesh
            MeshController outputMesh = new MeshController(guid);

            // Collect surfaces to export
            List <SurfaceBody> plannedSurfaces = GenerateExportList(group, outputMesh.Mesh.physics);

            // Export faces, multithreaded
            if (plannedSurfaces.Count > 0)
            {
                // Reset progress bar
                reporter?.Invoke(0, plannedSurfaces.Count);

                // Start jobs
                int    totalJobsFinished = 0;
                object finishLock        = new object(); // Used to prevent multiple threads from updating progress bar at the same time.

                Parallel.ForEach(plannedSurfaces, (SurfaceBody surface) =>
                {
                    CalculateSurfaceFacets(surface, outputMesh, RobotExporterAddInServer.Instance.AddInSettingsManager.DefaultExportWithColors, backgroundWorker);

                    lock (finishLock)
                    {
                        totalJobsFinished++;
                        reporter?.Invoke(totalJobsFinished, plannedSurfaces.Count);
                    }
                });
                if (backgroundWorker != null && backgroundWorker.CancellationPending)
                {
                    return(null);
                }

                outputMesh.DumpOutput();
            }

            return(outputMesh.Mesh);
        }
 public CustomRigidJoint(RigidBodyJoint joint, CustomRigidGroup groupOnez, CustomRigidGroup groupTwoz)
 {
     foreach (AssemblyJoint aj in joint.Joints)
     {
         joints.Add(aj);
     }
     foreach (AssemblyConstraint cj in joint.Constraints)
     {
         constraints.Add(cj);
     }
     groupOne = groupOnez;
     groupTwo = groupTwoz;
     type     = joint.JointType;
     joint.GetJointData(out geomOne, out geomTwo, out options);
     try
     {
         jointBased = options.get_Value("FromJoint");
     }
     catch
     {
         jointBased = false;
     }
 }
Beispiel #22
0
 public static SkeletalJoint_Base Create(CustomRigidJoint rigidJoint, CustomRigidGroup parent)
 {
     if (RotationalJoint.IsRotationalJoint(rigidJoint))
     {
         return(new RotationalJoint(parent, rigidJoint));
     }
     if (LinearJoint.IsLinearJoint(rigidJoint))
     {
         return(new LinearJoint(parent, rigidJoint));
     }
     if (CylindricalJoint.IsCylindricalJoint(rigidJoint))
     {
         return(new CylindricalJoint(parent, rigidJoint));
     }
     if (PlanarJoint.IsPlanarJoint(rigidJoint))
     {
         return(new PlanarJoint(parent, rigidJoint));
     }
     if (BallJoint.IsBallJoint(rigidJoint))
     {
         return(new BallJoint(parent, rigidJoint));
     }
     return(null);
 }
Beispiel #23
0
    /// <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, float totalMassKg)
    {
        SurfaceExporter surfs = new SurfaceExporter();

        BXDJSkeleton.SetupFileNames(baseNode);

        List <RigidNode_Base> nodes = new List <RigidNode_Base>();

        baseNode.ListAllNodes(nodes);

        List <BXDAMesh> meshes = new List <BXDAMesh>();

        SetProgress(0, "Exporting Model");

        for (int i = 0; i < nodes.Count; i++)
        {
            RigidNode_Base node = nodes[i];

            if (node is RigidNode && node.GetModel() != null && node.ModelFileName != null && node.GetModel() is CustomRigidGroup)
            {
                try
                {
                    CustomRigidGroup group = (CustomRigidGroup)node.GetModel();

                    BXDAMesh output = surfs.ExportAll(group, node.GUID, (long progress, long total) =>
                    {
                        SetProgress(((double)progress / total) / nodes.Count + (double)i / nodes.Count);
                    });

                    output.colliders.Clear();
                    output.colliders.AddRange(ConvexHullCalculator.GetHull(output));

                    meshes.Add(output);
                }
                catch (Exception e)
                {
                    throw new Exception("Error exporting mesh: " + node.GetModelID(), e);
                }
            }
        }

        // Apply custom mass to mesh
        if (totalMassKg > 0) // Negative value indicates that default mass should be left alone (TODO: Make default mass more accurate)
        {
            float totalDefaultMass = 0;
            foreach (BXDAMesh mesh in meshes)
            {
                totalDefaultMass += mesh.physics.mass;
            }
            for (int i = 0; i < meshes.Count; i++)
            {
                meshes[i].physics.mass = totalMassKg * (float)(meshes[i].physics.mass / totalDefaultMass);
            }
        }

        // Add meshes to all nodes
        for (int i = 0; i < meshes.Count; i++)
        {
            ((OGL_RigidNode)nodes[i]).loadMeshes(meshes[i]);
        }

        // Get wheel information (radius, center, etc.) for all wheels
        foreach (RigidNode_Base node in nodes)
        {
            SkeletalJoint_Base joint = node.GetSkeletalJoint();

            // Joint will be null if the node has no connection.
            // cDriver will be null if there is no driver connected to the joint.
            if (joint != null && joint.cDriver != null)
            {
                WheelDriverMeta wheelDriver = (WheelDriverMeta)joint.cDriver.GetInfo(typeof(WheelDriverMeta));

                // Drivers without wheel metadata do not need radius, center, or width info.
                if (wheelDriver != null)
                {
                    (node as OGLViewer.OGL_RigidNode).GetWheelInfo(out float radius, out float width, out BXDVector3 center);
                    wheelDriver.radius = radius;
                    wheelDriver.center = center;
                    wheelDriver.width  = width;

                    joint.cDriver.AddInfo(wheelDriver);
                }
            }
        }

        return(meshes);
    }
Beispiel #24
0
 public RigidNode(Guid guid, CustomRigidGroup grp)
     : base(guid)
 {
     this.group = grp;
 }
Beispiel #25
0
 public RigidNode(Guid guid)
     : base(guid)
 {
     group = null;
 }
Beispiel #26
0
    /// <summary>
    /// Merges any groups that are connected only with constraints and generate a node tree.
    /// </summary>
    /// <remarks>
    /// This starts at whichever rigid group is grounded, then branches out along rigid joints from there.
    /// If the rigid joint is movable (made of assembly joint(s)) then another node is created, if the joint
    /// is constraint-only then the leaf node is merged into the current branch.
    /// </remarks>
    /// <param name="results">Rigid results to clean</param>
    public static RigidNode BuildAndCleanDijkstra(CustomRigidResults results)
    {
        Dictionary <CustomRigidGroup, HashSet <CustomRigidGroup> > constraints = new Dictionary <CustomRigidGroup, HashSet <CustomRigidGroup> >();
        Dictionary <CustomRigidGroup, HashSet <CustomRigidGroup> > joints      = new Dictionary <CustomRigidGroup, HashSet <CustomRigidGroup> >();

        GenerateJointMaps(results, joints, constraints);

        // Mapping rigid group to merge-into group
        Dictionary <CustomRigidGroup, CustomRigidGroup> mergePattern = new Dictionary <CustomRigidGroup, CustomRigidGroup>();
        // Mapping rigid group to skeletal node
        Dictionary <CustomRigidGroup, RigidNode> baseNodes = new Dictionary <CustomRigidGroup, RigidNode>();
        // Deffered joint creation.  Required so merge can take place.
        List <PlannedJoint> plannedJoints = new List <PlannedJoint>();
        // The base of the skeletal tree
        RigidNode baseRoot = null;

        // All the currently open groups as an array {currentGroup, mergeIntoGroup}
        List <CustomRigidGroup[]> openNodes = new List <CustomRigidGroup[]>();
        // All the groups that have been processed.  (Closed nodes)
        HashSet <CustomRigidGroup> closedNodes = new HashSet <CustomRigidGroup>();

        // Find the first grounded group, the start point for dijkstra's algorithm.
        foreach (CustomRigidGroup grp in results.groups)
        {
            if (grp.grounded)
            {
                openNodes.Add(new CustomRigidGroup[] { grp, grp });
                closedNodes.Add(grp);
                baseNodes.Add(grp, baseRoot = new RigidNode(Guid.NewGuid(), grp));
                break; //Should only contain one grounded group, as they have all been merged together.
            }
        }
        Console.WriteLine("Determining merge commands");
        while (openNodes.Count > 0)
        {
            List <CustomRigidGroup[]> newOpen = new List <CustomRigidGroup[]>();
            foreach (CustomRigidGroup[] node in openNodes)
            {
                // Get all connections
                HashSet <CustomRigidGroup> cons = constraints[node[0]];
                HashSet <CustomRigidGroup> jons = joints[node[0]];
                foreach (CustomRigidGroup jonConn in jons)
                {
                    if (!closedNodes.Add(jonConn)) //Moves on to next if the connected component is already in closedNodes.
                    {
                        continue;
                    }
                    RigidNode rnode = new RigidNode(Guid.NewGuid(), jonConn); //Makes a new rigid node for the connected component.
                    baseNodes.Add(jonConn, rnode);

                    //Find the actual joint between the two components.
                    foreach (CustomRigidJoint jnt in results.joints)
                    {
                        if (jnt.joints.Count > 0 && ((jnt.groupOne.Equals(jonConn) && jnt.groupTwo.Equals(node[0])) ||
                                                     (jnt.groupOne.Equals(node[0]) && jnt.groupTwo.Equals(jonConn))))
                        {
                            PlannedJoint pJoint = new PlannedJoint();
                            pJoint.joint      = jnt;
                            pJoint.parentNode = baseNodes[node[1]];
                            pJoint.node       = rnode;
                            plannedJoints.Add(pJoint);
                            newOpen.Add(new CustomRigidGroup[] { jonConn, jonConn });
                            break;
                        }
                    }
                }
                foreach (CustomRigidGroup consConn in cons)
                {
                    if (!closedNodes.Add(consConn))
                    {
                        continue;
                    }
                    mergePattern.Add(consConn, node[1]);
                    newOpen.Add(new CustomRigidGroup[] { consConn, node[1] }); //Uses node[1] to ensure all constrained groups are merged into the same group.
                }
            }
            openNodes = newOpen;
        }

        Console.WriteLine("Do " + mergePattern.Count + " merge commands");
        //Transfers components between constrained groups.
        foreach (KeyValuePair <CustomRigidGroup, CustomRigidGroup> pair in mergePattern)
        {
            pair.Value.occurrences.AddRange(pair.Key.occurrences);          //Transfers key components to related value.
            pair.Key.occurrences.Clear();
            pair.Value.grounded = pair.Value.grounded || pair.Key.grounded; //Is it possible for the key to be grounded?  Would there have to be a loop of groups?
        }
        Console.WriteLine("Resolve broken joints");
        //Goes through each joint and sees if it was merged.  If it was, it attaches the group left behind to the group that was merged into.
        foreach (CustomRigidJoint joint in results.joints)
        {
            CustomRigidGroup updatedGroup = null; //Stores the group that the previous groupOne/Two was merged into.
            if (mergePattern.TryGetValue(joint.groupOne, out updatedGroup))
            {
                joint.groupOne = updatedGroup;
            }
            if (mergePattern.TryGetValue(joint.groupTwo, out updatedGroup))
            {
                joint.groupTwo = updatedGroup;
            }
        }
        Console.WriteLine("Creating planned skeletal joints");
        foreach (PlannedJoint pJoint in plannedJoints)
        {
            SkeletalJoint_Base sJ = SkeletalJoint.Create(pJoint.joint, pJoint.parentNode.group);
            pJoint.parentNode.AddChild(sJ, pJoint.node);
        }
        Console.WriteLine("Cleanup remainders");
        CleanMeaningless(results);
        return(baseRoot);
    }