.. _ForceFields: ======================= Force Fields ======================= The Force Fields extension provides several methods that apply forces to the physics objects in the scene causing them to move in interesting ways. These methods, called force fields, can be added on top of each other to generate new behaviors. Each force field can be positioned, oriented and animated in the world to achieve the desired effect. Getting Started ----------------------------- The PhysX Force Fields extension (omni.physx.forcefields) requires that the USD Force Field Schema (omni.usd.schema.forcefield) be enabled first. To enable both extensions, open the Extension Manager using the **Window > Extensions** menu item. Enter "force" into the search box to find the two extensions. The USD Force Field Schema must be auto loaded when Kit launches because the PhysX Force Fields extension depends on it. Click on the USD Force Field Schema and then check the **Autoload** check box. Next exit Kit using the **File > Exit** command and then relaunch it. Re-open the Extension Manager, find the PhysX Force Fields extension and then check the **Autoload** check box, if it should be active every time Kit is launched, or slide the enabled switch to on to only use it temporarily. Introduction to Force Fields ################################## A force field is a mathematical function that computes a force vector to apply to a physics object as a function of time and its position, orientation, velocity and angular rate. The force fields are programmed and compiled in C++ because they are intended to act on very large numbers of objects and must execute very quickly. The current list of force fields include: Spherical, Planar, Linear, Drag, Wind and Noise. Additional force fields will be released in later versions. These basic force fields are applied to a prim in the scene. Ideally, an Xform prim will be used so it can be positioned and oriented on the stage through its transformation matrix, but this is not required. Each force field does include a Position property that can be set, instead. However, the transform matrix takes precedence if both are available. Multiple force fields can be applied to a single prim and multiple force fields can act on the physics objects. The forces are simply added together to determine the net force acting on it. By default, force fields act on all of the physics objects in the scene. But this can be changed by editing the USD Collection to include or exclude prims and their children. Demos ######## The Force Fields extension provides a few sample scenes that can be loaded quickly to see how force fields can be used. Open the Physics Demo Scenes: **Window > Simulation > Demo Scenes** In the Physics Demo Scenes Tab, click on the Demos list to find the force field samples, which all start with the, "ForceField" prefix. .. image:: ../content/images/force_field_samples.jpg :align: center :alt: ForceFieldSamples For the purposes of this introduction, select the ForceFieldExplode sample and click **Load scene**. .. image:: ../content/images/force_field_load_scene.jpg :align: center :alt: ForceFieldLoadScene Press the Play button to start the simulation and watch the demonstration. .. video:: ../content/video/force_field_demo_explode.m4v :width: 100% :centered: :alt: Force Field Explode Demo The following Python script is used to set up the force fields used in this demo and then animate their **Enabled** flags to achieve this result. An explanation of this script, how to programmatically set up force fields, which physics objects they affect and how to animate them is presented in :ref:`Using_Force_Fields_In_Python_label` .. code-block:: python :linenos: import math import os import random from pxr import Gf, Sdf, Usd from pxr import UsdGeom, UsdUtils, UsdPhysics from pxr import PhysxSchema, PhysicsSchemaTools, ForceFieldSchema import omni.physx.scripts.physicsUtils as physicsUtils import omni.kit import omni.physxdemos as demo class ExplodeForceFieldDemo(demo.Base): title = "ForceFieldExplode" category = demo.Categories.DEMOS short_description = "Suck objects together before they are blown apart." description = "Use two spherical force fields to first attract objects to a central point and then explode them apart." def create(self, stage): numberOfBoxes = 20 boxSpacing = 2 boxPathName = "/box" groundPathName = "/ground" scenePathName = "/World/scene" explodePathName = "/World/explode" # Physics scene up = Gf.Vec3f(0.0) up[1] = 1.0 gravityDirection = -up gravityMagnitude = 1000.0 forceRange = Gf.Vec2f(-1.0) center = Gf.Vec3f(0.0) center[1] = 400.0 scene = UsdPhysics.Scene.Define(stage, scenePathName) scene.CreateGravityDirectionAttr(gravityDirection) scene.CreateGravityMagnitudeAttr(gravityMagnitude) # Plane physicsUtils.add_ground_plane(stage, groundPathName, "Y", 750.0, Gf.Vec3f(0.0), Gf.Vec3f(0.5)) # Create the force field prim xformPrim = UsdGeom.Xform.Define(stage, explodePathName) xformPrim.AddTranslateOp().Set(Gf.Vec3f(0.0, 300.0, 0.0)) explodePrim = xformPrim.GetPrim() suckPrimApi = ForceFieldSchema.PhysxForceFieldSphericalAPI.Apply(explodePrim, "Suck") suckPrimApi.CreateConstantAttr(-1e10) suckPrimApi.CreateLinearAttr(0.0) suckPrimApi.CreateInverseSquareAttr(0.0) suckPrimApi.CreateEnabledAttr(False) suckPrimApi.CreatePositionAttr(Gf.Vec3f(0.0, 0.0, 0.0)) suckPrimApi.CreateRangeAttr(Gf.Vec2f(-1.0, -1.0)) explodePrimApi = ForceFieldSchema.PhysxForceFieldSphericalAPI.Apply(explodePrim, "Explode") explodePrimApi.CreateConstantAttr(4e10) explodePrimApi.CreateLinearAttr(0.0) explodePrimApi.CreateInverseSquareAttr(0.0) explodePrimApi.CreateEnabledAttr(False) explodePrimApi.CreatePositionAttr(Gf.Vec3f(0.0, 0.0, 0.0)) explodePrimApi.CreateRangeAttr(Gf.Vec2f(-1.0, -1.0)) dragPrimApi = ForceFieldSchema.PhysxForceFieldDragAPI.Apply(explodePrim, "Drag") dragPrimApi.CreateMinimumSpeedAttr(10.0) dragPrimApi.CreateLinearAttr(1.0e6) dragPrimApi.CreateSquareAttr(0.0) dragPrimApi.CreateEnabledAttr(False) dragPrimApi.CreatePositionAttr(Gf.Vec3f(0.0, 0.0, 0.0)) dragPrimApi.CreateRangeAttr(Gf.Vec2f(-1.0, -1.0)) # Add the collection collectionAPI = Usd.CollectionAPI.ApplyCollection(explodePrim, ForceFieldSchema.Tokens.forceFieldBodies) collectionAPI.CreateIncludesRel().AddTarget(stage.GetDefaultPrim().GetPath()) # Boxes boxSize = Gf.Vec3f(100.0) boxPosition = Gf.Vec3f(0.0) m = (int)(math.sqrt(numberOfBoxes)) for i in range(m): for j in range(m): boxPath = boxPathName + str(i) + str(j) boxPosition[0] = (i + 0.5 - (0.5 * m)) * boxSpacing * boxSize[0] boxPosition[1] = 0.5 * boxSize[1] boxPosition[2] = (j + 0.5 - (0.5 * m)) * boxSpacing * boxSize[2] boxPrim = physicsUtils.add_rigid_box(stage, boxPath, position=boxPosition, size=boxSize) # Animate the force fields on and off global time time = 0.0 def force_fields_step(deltaTime): global time time = time + deltaTime if time > 4.1: suckPrimApi.GetEnabledAttr().Set(False) explodePrimApi.GetEnabledAttr().Set(False) dragPrimApi.GetEnabledAttr().Set(False) elif time > 4.0: suckPrimApi.GetEnabledAttr().Set(False) explodePrimApi.GetEnabledAttr().Set(True) dragPrimApi.GetEnabledAttr().Set(False) elif time > 2.0: suckPrimApi.GetEnabledAttr().Set(True) explodePrimApi.GetEnabledAttr().Set(False) dragPrimApi.GetEnabledAttr().Set(True) else: suckPrimApi.GetEnabledAttr().Set(True) explodePrimApi.GetEnabledAttr().Set(False) dragPrimApi.GetEnabledAttr().Set(False) def timeline_event(event): # on play press if event.type == int(omni.timeline.TimelineEventType.PLAY): global time time = 0.0 # on stop press if event.type == int(omni.timeline.TimelineEventType.STOP): pass physxInterface = omni.physx.get_physx_interface() self._subscriptionId = physxInterface.subscribe_physics_step_events(force_fields_step) timelineInterface = omni.timeline.get_timeline_interface() stream = timelineInterface.get_timeline_event_stream() self._timeline_subscription = stream.create_subscription_to_pop(timeline_event) Please feel free to explore the other demos and their scripts. .. video:: ../content/video/force_field_demo_levitate.m4v :width: 100% :centered: :alt: Force Field Levitate Demo .. video:: ../content/video/force_field_demo_wind.m4v :width: 100% :centered: :alt: Force Field Wind Demo .. video:: ../content/video/force_field_demo_spin.m4v :width: 100% :centered: :alt: Force Field Spin Demo Adding Force Fields ---------------------------------------------------------- There are two ways to apply force fields to a prim. The first method uses the Add button on in the Property window. Click on the desired prim. Click the Property tab and then click the **Add** button. A pop up menu will appear. Select the **Physics** submenu and then select the desired force field to add. .. image:: ../content/images/force_field_add_property.jpg :align: center :alt: ForceFieldAddProperty A second method involves right clicking on the prim itself in the **Stage** window. A pop up menu will appear with the **Add > Physics** sub menus. Then select the desired force field. .. image:: ../content/images/force_field_stage_add_property.jpg :align: center :alt: ForceFieldStageAddProperty Spherical Force Field ---------------------------------------------------------- The spherical force field attracts or repels objects to a central point while it is enabled. The following list of properties are available. ============================ ==================== Property Description ============================ ==================== Enabled | Turns the force field on or off. Position | The location of the force field in the world coordinate frame. Range | Forces are only applied when the physics object is within this minimum and maximum distance from the force field position. A negative distance disables that value. e.g. Setting the minimum and maximum to (-1.0, -1.0) applies forces to objects regardless of their distance. Constant | A constant force is applied to the physics object regardless of its distance to the force field position. Negative values attract and positive values repel. Linear | A force that varies linearly with the distance from the force field position, i.e. F = k x d. Negative values attract and positive values repel. Inverse Square | A force that is inversely proportional to the square of the distance from the force field. i.e. F = k / d^2. Negative values attract and positive values repel. ============================ ==================== .. image:: ../content/images/force_field_spherical_property.jpg :align: center :alt: ForceFieldSphericalProperty Drag Force Field ---------------------------------------------------------- The drag force field generates forces that slow objects down by generating forces that oppose their velocity. The following list of properties are available. ============================ ==================== Property Description ============================ ==================== Enabled | Turns the force field on or off. Position | The location of the force field in the world coordinate frame. Range | Forces are only applied when the physics object is within this minimum and maximum distance from the force field position. A negative distance disables that value. e.g. Setting the minimum and maximum to (-1.0, -1.0) applies forces to objects regardless of their distance. Minimum Speed | Drag forces will not be applied when the speed of the physics object is below this minimum. A setting of -1.0 disables this minimum. Linear | The force varies linearly with the speed of the physics object. D = k x s. Square | The force varies with the square of the speed of the physics object. D = k x s^2. This is similar to an aerodynamic drag force. ============================ ==================== .. image:: ../content/images/force_field_drag_property.jpg :align: center :alt: ForceFieldDragProperty Linear Force Field ---------------------------------------------------------- The linear force field generates forces that attract or repel physics objects from the closest point on a line. No force is applied along the direction of the line. The following list of properties are available. ============================ ==================== Property Description ============================ ==================== Enabled | Turns the force field on or off. Position | The location of the force field in the world coordinate frame. Range | Forces are only applied when the physics object is within this minimum and maximum distance from the force field position. A negative distance disables that value. e.g. Setting the minimum and maximum to (-1.0, -1.0) applies forces to objects regardless of their distance. Direction | A vector with a length of one, in local space, that describes the orientation of the line. Constant | A constant force is applied to the physics object regardless of its distance to the line. Negative values attract and positive values repel. Linear | A force that varies linearly with the distance from the line, i.e. F = k x d. Negative values attract and positive values repel. Inverse Square | A force that is inversely proportional to the square of the distance from the line. i.e. F = k / d^2. Negative values attract and positive values repel. ============================ ==================== .. image:: ../content/images/force_field_linear_property.jpg :align: center :alt: ForceFieldLinearProperty Spin Force Field ---------------------------------------------------------- The spin force field generates forces that cause physics objects to spin around a line. No force is applied along the direction of the spin axis. The only difference between this force field and the linear force field the is direction of the resulting force. This linear force field generates forces towards the line, while the spin force field generates forces that are perpendicular to the line. The following list of properties are available. ============================ ==================== Property Description ============================ ==================== Enabled | Turns the force field on or off. Position | The location of the force field in the world coordinate frame. Range | Forces are only applied when the physics object is within this minimum and maximum distance from the force field position. A negative distance disables that value. e.g. Setting the minimum and maximum to (-1.0, -1.0) applies forces to objects regardless of their distance. Spin Axis | A vector with a length of one, in local space, that describes the orientation of the line. Constant | A constant force is applied to the physics object regardless of its distance to the spin axis. Negative values attract and positive values repel. Linear | A force that varies linearly with the distance from the spin axis, i.e. F = k x d. Negative values attract and positive values repel. Inverse Square | A force that is inversely proportional to the square of the distance from the spin axis. i.e. F = k / d^2. Negative values attract and positive values repel. ============================ ==================== .. image:: ../content/images/force_field_spin_property.jpg :align: center :alt: ForceFieldSpinProperty Planar Force Field ---------------------------------------------------------- The planar force field generates forces that cause physics objects to be attracted to or repelled away from a plane. The following list of properties are available. ============================ ==================== Property Description ============================ ==================== Enabled | Turns the force field on or off. Position | The location of the force field in the world coordinate frame. Range | Forces are only applied when the physics object is within this minimum and maximum distance from the force field position. A negative distance disables that value. e.g. Setting the minimum and maximum to (-1.0, -1.0) applies forces to objects regardless of their distance. Normal | A vector with a length of one, in local space, that describes the normal vector, or orientation, of the plane. Constant | A constant force is applied to the physics object regardless of its distance to the plane. Negative values attract and positive values repel. Linear | A force that varies linearly with the distance from the plane, i.e. F = k x d. Negative values attract and positive values repel. Inverse Square | A force that is inversely proportional to the square of the distance from the plane. i.e. F = k / d^2. Negative values attract and positive values repel. ============================ ==================== .. image:: ../content/images/force_field_planar_property.jpg :align: center :alt: ForceFieldPlanarProperty Noise Force Field ---------------------------------------------------------- The noise force field generates random forces that cause physics objects to move in a chaotic fashion. The forces change their magnitude and direction smoothly over time. The following list of properties are available. ============================ ==================== Property Description ============================ ==================== Enabled | Turns the force field on or off. Position | The location of the force field in the world coordinate frame. Range | Forces are only applied when the physics object is within this minimum and maximum distance from the force field position. A negative distance disables that value. e.g. Setting the minimum and maximum to (-1.0, -1.0) applies forces to objects regardless of their distance. Drag | The drag coefficient determines the magnitude of the force that attempts to align the velocity of the physics object with the noise velocity. Higher values cause the physics objects to change direction more quickly. Amplitude | The maximum magnitude of the noise signal. Frequency | The frequency at which the noise signal oscillates. ============================ ==================== .. image:: ../content/images/force_field_noise_property.jpg :align: center :alt: ForceFieldNoiseProperty Wind Force Field ---------------------------------------------------------- The wind force field causes physics objects to move as if they are blowing in a wind. The wind can vary in wind speed and direction. The following list of properties are available. ============================ ==================== Property Description ============================ ==================== Enabled | Turns the force field on or off. Position | The location of the force field in the world coordinate frame. Range | Forces are only applied when the physics object is within this minimum and maximum distance from the force field position. A negative distance disables that value. e.g. Setting the minimum and maximum to (-1.0, -1.0) applies forces to objects regardless of their distance. Drag | The drag coefficient determines the magnitude of the force that attempts to align the velocity of the physics object with the wind velocity. Higher values cause the physics objects to change direction more quickly. Average Speed | The average speed of the wind. Speed Variation | The maximum magnitude of the change in wind speed. Speed Variation Frequency | The frequency at which the wind speed changes. Average Direction | A vector of unit length that describes the direction in which the wind is blowing. Direction Variation | A vector of arbitrary length that describes the maximum magnitude of the changes in the wind direction vector along each axis of the local space. The wind direction will be re-normalized into a unit vector after the randomized component is applied. Direction Frequency | The frequency at which the wind direction oscillates. ============================ ==================== .. image:: ../content/images/force_field_wind_property.jpg :align: center :alt: ForceFieldWindProperty Collections ---------------------------------------------------------- The forces generated by the force fields on a prim are applied to the set of rigid bodies specified by the, "forceFieldBodies" USD Collection. This USD collection is currently listed in the **Raw USD Properties** box, but will be moved into a more visible Property window of its own. Upon initialization, the default prim, "/World" is added to the includes list and the expansionRule is set to expandPrims. The expandPrims setting includes all of the children in the hierarchy of the prims listed, so in this case, every prim in the "/World" will be affected by the force fields. Multiple prims can be added to the **includes**. Click the **Add Target(s)** button and select the prims to include from the list. If the **expansionRule** is set to explicitOnly, then only the prims themselves, and none of their children will be affected by the force fields. Another checkbox, **includeRoot** specifies whether the prim listed in the includes list should, itself, have forces applied to it. The default setting is to include the root. To prevent specific rigid bodies from receiving forces, add the prims to the **excludes** list. Multiple prims can be added to the list. The rules work in the same way. If the **expansionRule** is set to expandPrims, then the children of the listed prims are also excluded. If the **includeRoot** checkbox is checked, then root itself is also excluded. .. image:: ../content/images/force_field_collection.jpg :align: center :alt: ForceFieldCollection Multiple collections can also be used. Create a second prim, **Add** new force fields to that prim and then unique includes and excludes lists can be specified. Tuning the Force Field Properties ---------------------------------------------------------- The most difficult part of using the force fields extension is tuning the force coefficients labeled Constant, Linear, InverseSquare and Drag. These settings will depend on the masses of the rigid bodies that are being affected, so the more massive the object to be moved, the larger the setting should be. However, since lighter objects need to accelerate faster than heavier objects inside a force field, this difficulty is necessary. It just takes time to find settings that generate the desired results. The following suggestions should make it a bit easier. A recommended approach is to first determine whether to use the Constant, Linear or Inverse Square as the primary property. Constant generates a force that will accelerate objects at a steady rate. The Linear force generates behaviors similar to a spring that results in sinusoidal motion. The Inverse Square term is how gravity is modelled. It tends to attract or repel very slowly at large distances but generates extremely strong forces nearby. Do the tuning while the simulation is running. This avoid the necessity to continuously press the simulation Start and Stop buttons. Next, determine the correct order of magnitude for the force. Start by setting the coefficient to 1e0, and continue increasing the exponent until the rigid body objects start to move (1e1, 1e2, 1e3, etc.). Once the order of magnitude is known, adjust the mantissa to fine tune the results. .. _Using_Force_Fields_In_Python_label: Using Force Fields In Python ---------------------------------------------------------- Setting up force fields in Python uses script to run through the same steps as going through the UI. The only difference is that the "forceFieldBodies" USD Collection must be created manually. The creation of a Physics scene, ground plane and the rigid bodies themselves is also required, but not covered here. The first step is to create a prim to hold all of the force fields. Add a translate operation to create a transformation matrix that can be positioned and animated. .. code-block:: python :linenos: from pxr import ForceFieldSchema # Create the force field prim xformPrim = UsdGeom.Xform.Define(stage, "/World/Prim") xformPrim.AddTranslateOp().Set(Gf.Vec3f(0.0, 300.0, 0.0)) prim = xformPrim.GetPrim() Next, create the various force fields by applying them to the new prim and creating the attributes that need to be changed. .. code-block:: python :linenos: explodePrimApi = ForceFieldSchema.PhysxForceFieldSphericalAPI.Apply(prim, "Explode") explodePrimApi.CreateConstantAttr(4e10) explodePrimApi.CreateLinearAttr(0.0) explodePrimApi.CreateInverseSquareAttr(0.0) explodePrimApi.CreateEnabledAttr(True) explodePrimApi.CreatePositionAttr(Gf.Vec3f(0.0, 0.0, 0.0)) explodePrimApi.CreateRangeAttr(Gf.Vec2f(-1.0, -1.0)) To create the USD Collection, use the following lines of code. This will include all rigid bodies in the scene. .. code-block:: python :linenos: # Add the collection collectionAPI = Usd.CollectionAPI.ApplyCollection(prim, ForceFieldSchema.Tokens.forceFieldBodies) collectionAPI.CreateIncludesRel().AddTarget(stage.GetDefaultPrim().GetPath()) The previous steps are sufficient to get the force fields to work and affecting the rigid bodies in the scene. But it is also possible to animate any of the USD properties while the simulation is running. To do this, add a call back in the script that can be used to update the settings. Be sure to save the subscription ID's in the class or they will be destroyed and the callback functions will not be called. .. code-block:: python :linenos: global time time = 0.0 def force_fields_step(deltaTime): global time time = time + deltaTime if time > 2.0: explodePrimApi.GetEnabledAttr().Set(False) else: explodePrimApi.GetEnabledAttr().Set(True) def timeline_event(event): # on play press if event.type == int(omni.timeline.TimelineEventType.PLAY): global time time = 0.0 # on stop press if event.type == int(omni.timeline.TimelineEventType.STOP): pass physxInterface = omni.physx.get_physx_interface() self._subscriptionId = physxInterface.subscribe_physics_step_events(force_fields_step) timelineInterface = omni.timeline.get_timeline_interface() stream = timelineInterface.get_timeline_event_stream() self._timeline_subscription = stream.create_subscription_to_pop(timeline_event)