< All Topics
Dynamic : RigidPart
PostedFebruary 1, 2023
UpdatedFebruary 8, 2023
Simon Fjordvald
Dynamic is primarily used as the base class for Loads in Experior. Since there is potential for a lot more active Loads than Parts/Machinery in an Experior model, Dynamic implements simplified models, cutting 3D model complexity for performance gains.
A Dynamic load 3D model is collapsed into a streamlined format that strips away some of the functionality seen in Static. For instance, Loads only applies one material color to the entire 3D model instead of iterating through all materials. Visual complexity could be achieved by applying a texture to the model.
Models deriving from Dynamic relates to models (Loads) that act on physics forces applied by other 3D objects (conveyors for instance). Loads are meant to be moved by the NVIDIA PhysX engine, to transport them along conveyor paths in an Experior model. Most importantly, Dynamic models are affected by a gravity force to drive their transportation through an Experior model. In Experior’s Discrete Events mode, Dynamic can be attached to a Load, which will not be affected by physics forces.
The collection below shows examples of models imported by classes deriving from Dynamic.
Bag as it is loaded in Experior.
Dispense Box as it is loaded in Experior.
EuroPallet as it is loaded in Experior.
Loaded Europallet as it is loaded in Experior.
Stack of Newspapers as it is loaded in Experior.
Package as it is loaded in Experior.
Plastic Euro Pallet as it is loaded in Experior.
Suitcase as it is loaded in Experior.
Methods and Properties
Dynamic implements physics related properties and methods, as well as overriding some of the basic definitions from RigidPart.
Note: We are working on creating a complete list which can be found in the API Dynamic documentation.
The following physics related concepts are implemented:
- CreateActor()
- NVIDIA Physics core concept, defining an actor that behaves based on physics. A Dynamic Part is added as an actor.
- Also implements ReCreateActor(), which calls this method each time a property value affecting its size or rigid shape is modified, setting the newly created actor’s global position/orientation to the previous actor’s values.
- NVIDIA Physics core concept, defining an actor that behaves based on physics. A Dynamic Part is added as an actor.
- Kinematic (true/false)
- A Kinematic = true actor will act as if it has infinite mass, which means it can push regular non-kinematic dynamic actors away, but cannot be pushed back itself. Secondly, if movement is intended for the Part, the programmer must define the actor’s movement each time step, which can be useful if it is desirable that the object should follow a specific pre-defined path.
- Rigid – Matters in defining how the actor behaves when collisions occur. Also defines how precise the collision should be (as in how closely collision detection point matches point on the mesh) – this is also a question of performance, where rigid body shape complexity increases performance cost.
- Rigid body shape – has the following options:
- None
- Box (Default)
- Rounded
- Dice
- Sphere
- Convex
- Rigid body shape – has the following options:
- Linear/Angular Dampening
- Linear/Angular Velocity
- Center of Mass Position
- When the physics engine applies a force to a Load to make it move, the force is applied into its center of mass. By default, a Load’s density is equally distributed over the whole volume of the Load and hence the center of mass of the Load is also its geometrical center. By providing the Center
Of Mass Offset Local Position, it is possible to move this center of mass and potentially place the center of mass lower than the geometrical center to, decrease the collapsing of a Load. - Note: The value provided to this property is an absolute value. The Center
Of Mass Offset Local Position property provided in the property window of a feeder is a normalised value, where 0:0:0 is center of the Load and 0:1:0 would be at the top-center position.
- When the physics engine applies a force to a Load to make it move, the force is applied into its center of mass. By default, a Load’s density is equally distributed over the whole volume of the Load and hence the center of mass of the Load is also its geometrical center. By providing the Center
- Collision detection (true/false)
- Default: true
- Density – used in calculating Load’s weight, which in Experior is Density * Volume.
- Add Force()/Torque()
- Sleep()/Wake() – Physics concept of enable/disable. Setting a Load as “Sleeping”, means it will no longer responds to physical forces applied to it, until it is enabled/woken up again.
Adding a Dynamic based Load
Custom Load classes in Experior derive from the Load base class in the Experior.Core.Loads namespace, where the custom Load class implements a Part that derives from Dynamic.
Let’s look at an example that demonstrates how a EuroPallet load type could be implemented in Experior.
The EuroPallet class defines a EuroPallet constructor which takes a PalletInfo object as an argument, which further derives from LoadInfo class, where info.<insertfield> fields are defined.
Inside the constructor, a new Part is created and positioned/oriented correctly alongside updating the info object with the correct information, which ensures the model can be re-created when loaded from a save file.
public class EuroPallet : Load
{
public EuroPallet(PalletInfo info) : base(info)
{
Part = new PalletPart(info.randomcolor ? Colors.GetRandomColor() : Info.color, // Part color
1.2f, 0.144f, 0.8f, // Part size (Length, Height, Width)
info.density, // Part density
EmbeddedResources.EmbeddedResourceLoader.Get("EUROpallet.dae"), // Get embedded 3D model resource
info.rigid, // Define Rigid shape
this); // ILoad parent
Part.Position = Info.position;
Part.Orientation = Info.rotation;
info.height = ((PalletPart)Part).Height;
info.length = ((PalletPart)Part).Length;
info.width = ((PalletPart)Part).Width;
info.color = Part.Color;
}
}
The PalletPart class, which derives from Dynamic, gets the correct mesh from an embedded resource by importing it, scales the mesh to input size and sets a centerofmass point value. The latter value matters for physics forces, which are applied to an objects center of mass point.
internal class PalletPart : Dynamic
{
private EmbeddedResource resource;
private int textureId = -1;
[Browsable(false)]
public override int TextureId =>; textureId;
public PalletPart(Color color, // Part color
float length, // Part length
float height, // Part height
float width, // Part width
float density, // Part density
EmbeddedResource resource, // Embedded resource file reference
Rigids rigid, // Rigid shape
ILoad parent) // ILoad parent
: base(parent)
{
try
{
this.density = density;
this.resource = resource;
// Import Embedded resource mesh, its meshdata color and ID reference to mesh texture
Importer.GetMesh(resource, out meshData, out this.color, out textureId);
// At the time of writing, Experior handles Load coloring with 2 special cases by:
// * transparent = random color
// * black = mesh color
// This if clause means if (input) color != black, set mesh color (this.color) to input color
// if (input) color is black, it uses outed mesh color (this.color) as load color
// Color handling is to be refactored in a future Experior major version.
if (color != System.Windows.Media.Colors.Black)
{
this.color = color;
}
this.rigid = rigid;
scale = new Vector3(1, 1, 1);
Vector3 size = MeshData.BoundingBox.Size;
// Calculate proper scalar based on mesh bounding box size
if (length > 0 && height > 0 && width > 0)
{
scale = new Vector3(length / size.X, height / size.Y, width / size.Z);
}
// Define center of mass point
centerofmass = new Vector3(0, -Height / 2.5f, 0);
Observers.MeshObjectObserver.Added(this);
}
catch (Exception se)
{
Log.Write(se, 0933886);
}
}
}
A CreateEuroPallet() method could then finally be defined as:
public static Load CreateEuroPallet(string barcode, float density, Color color, Rigids rigid)
{
var info = new PalletInfo
{
barcode = barcode,
rigid = rigid,
density = density,
color = color
};
var load = new EuroPallet(info);
// Position the load at half the load's height. (Positions the load from its centerpoint).
load.Position = new Vector3(0, load.Height / 2, 0);
// Add to collection of loads added to the scene.
items.Add(load);
return load;
}
In Experior, the CreateEuroPallet() method is called when the “Feeder” assembly in the Conveyor catalog “feeds” a new load, either from a double-click event on the 3D cube model or pressing the spacebar when it is selected.