Physics

Introduction

Omniverse Create features real time physics simulation. Create relies on the NVIDIA PhysX SDK for rigid body dynamics and NVIDIA Flow for fluid dynamics.

Note

The Physics integration still has the following known issues: - Undo is not yet implemented for many physics editing operations. - Most of the editing user interface and workflow is preliminary. - Pairwise collision filters that have been set cannot be removed.

Rigid Body Dynamics

Getting Started

To start using physics simulation, the appropriate extensions must be enabled. Currently the following extensions are available:

Extension

Description

omni.physx

Basic functionality

omni.physx.cct

Character controller

omni.physx.computegraph

Needed for cloth attachments

omni.physx.ui

Physics graphical user interface

omni.physx.vehicle

Physics vehicles

Make sure that you have enabled these extensions in the Window->Extension Manager window.

../_images/main_report_problem.png

Adding Basic Physics to Your Scene

Before you can have anything that behaves physically in your scene, you need to add a PhysicsScene. This object holds basic physics settings like gravity. All physical objects have to be tied to a physics scene. To create a scene, select Physics > Add > Physics Scene.

Often it makes sense to create these physics objects in their own layer.

Select the scene in the stage view; the details pane will now let you change important simulation settings such as gravity. As long as you only have a single PhysicsScene in your scene, it will act as the default and all physics object will automatically be associated with it.

The next most important thing you will generally need in your scene are static colliders. These are objects that don’t move (unless you move them) that will however collide with physical objects, such as the walls of a room. The simplest case is a so called ground plane, which can be created via Physics > Add > Ground Plane. This will add a new object comprised of a big quad visual and a static Plane collider. This will prevent your dynamic objects from falling indefinitely.

If you have your own mesh or prim geometry that you would like to make into a collider, just select it and then click Physics > Set > Collider. Instead of creating a new USD object, this will simply add phyics collision attributes to the existing object. The precise set of attributes added may depend on the kind of object you have selected.

Finally, to make something into a dynamic rigid body, select it, and then click Physics > Set > Rigid Body. In addition to adding colliders, this will also add rigid body attributes. Note that when you select an entire subtree of objects, collision attributes will be added to every applicable geometry, while the rigid body attributes are only added to the topmost node in the selection. This means that all parts of your selection will collide with the world, and everything parented under the topmost node will move together with it as a rigid assembly. Notice that additional physics attributes have been added to your details pane.

An object can only be made to move as a single unit. If you have multiple things combined together into a single mesh object, you will need to separate them into parts first, before physics can make them move independently.

Once you have a dynamic object defined, you can press the Play button. If you did everything right, this will make the object start falling until it hits your static object or ground plane, and comes to rest. Pressing stop will (by default) reset your simulation state to how it was before you pressed Play. While the simulation is running, you can also drag the dynamic object(s) around by shift-clicking and dragging them. They should follow your mouse cursor but still collide with obstacles.

Note

  • The Physics > Create menu creates new prims in your stage.

  • The Physics > Set menu adds an API to your selection.

  • The Physics > Collision Mesh Approximation and Physics > Joint Attributes menus set preferences for the next collision creation or Physics > Add > Joint operation respectively. They do not modify the currently selected prim.

Physics Properties

Currently because of some limitations with the main details pane, some physics settings are only visible in the dedicated Window > Physics > Physics Properties window. Open this window now while you have a dynamic rigid body selected.

Notice that there are some rollouts labeled “Physics” and some rollouts labeled “PhysX”. Physics properties are general, portable things that can reasonably be expected to work in the same or very similar ways in all other DCC tools with physics. PhysX attributes on the other hand are more advanced things that will likely only work in Omniverse Create or other tools that use NVIDIA PhysX as their underlying engine.

At the top of the Physics Properties window are two important drop-downs. The first is Add Prim Component. By default not all attributes that a physical object is able to have are immediately available. Some need to be added manually. For example, by default, masses are not set explicitly but are computed based on the volume of the object. If you would like to override this with an explicit mass, you can MassAPI::mass. This adds a Mass properties rollout that lets you set the mass. Another use case here is if you just want to add a Physics API to create a dynamic object, but you don’t want to also automatically create colliders for everything under its subtree.

Remove Prim Component is useful when you want to remove physical attributes from an object again. This dropdown contains the classes of attributes that have been added already and can be again removed.

The physics enabled check box can be used to temporarily freeze a dynamic object without completely removing its PhysicsAPI.

The kinematic enabled check box is for making animated key frame objects that can ‘push’ dynamic physics objects. First you need to key frame animate the object (see the Animation section of this guide), then just tick that check box and it should just work.

Mass Computation

By default, the mass of a dynamic body is derived from the total volume of all the collision geometry under the body, multiplied by a density. Unless a density is specified explicitly, a default of 1000 will be used. One can set an explicit density on any collider by adding a MassAPI::density component. In a hierarchy, a child’s prim’s density overrides parent prim’s density. However, a parent’s explicit mass set via MassAPI::mass will override a child’s density derived mass. It is also possible to have a density set in a PhysicsMaterial, which has the weakest precedence. Physics materials will be discussed later.

Collision Shape Settings

Colliders have three main settings:

Attribute

Description

collisionEnabled

Can be used to disable collision behavior temporarily.

physics material

Can reference a PhysicsMaterial to define surface properties.

collision group

Can reference a CollisionGroup to precisely define what pairs do or do not collide.

There is one attribute that only shows up for meshes but not for prims: collision approximation. This controls if the mesh should receive very coarse collision in the form of a box or sphere, a fitted convex hull, or even a decomposition into convex pieces. Note that PhysX doesn’t currently support collision between two dynamic triangle meshes.

Physics Materials

Physics materials can be created via Physics > Add > PhysicsMaterial. This will create a material object that can be assigned to colliders using the physics material attribute documented above. Eventually this will just be a component that can be added to graphical materials.

The physics material has friction, restitution (a.k.a. ‘bouncyness’) and material density parameters.

Collision Groups

Collision groups are groups that colliders can belong to. Once you have multiple collision groups, you can set them up to collide with eachother or not. You can create a collision group object using Physics > Add > Collision Group. You can now references this collision group via a collider’s collision group attribute. All things using the same collision group will collide with eachother. By default things in two different collision groups will also collide. In the PhysX properties pane of the collision group, however, you can add a list of other collision groups this group should not collide with. Scenes have a flag that lets you invert this behavior, in case you prefer that by default different groups should not collide, and then specify pairs of collision groups that do collide.

Pairwise Collision Filter

In cases where using collision groups is insufficiently fine grained, one may select two bodies, colliders or articulations, and choose Physics > Add > Pair Collision Filter. This will disable collision between only the pair of selected objects. This takes precedence over collision groups.

Joints

Joints give you the ability to connect rigid bodies in ways that are not entirely rigid. A good example is a car: the wheels of the car revolve around their respective axes, the suspension can slide up and down along an axis. The technical terms for the former is “revolute joint”, the second is a “prismatic joint”.

To add a joint to your scene, first select the type of joint you want using Physics > Set > Joint attributes > Type > … You can then add such a joint to your scene under Physics > Add > Joint > … There are three options here: to world, to parent, or between selected. The last option needs you to select two objects by control clicking them for it to be available.

When the joint is selected, its joint gizmo will be drawn. This is the usual coordinate frame in the 3d view, along with some joint type specific visualization to indicate the joint’s field of motion. The joint can be translated or rotated using this gizmo as if it was any other kind of 3d object.

The PhysX properties pane of the newly created joint will show its properties:

Attribute

Description

jointEnabled

Can be used to disable the joint temporarily.

axis

for some joint types, selects the axis of the gizmo along which the joint rotates or slides.

break force

If the joint experiences more strain than this during simulation, it will disconnect.

joint friction

The joint will have resistance to moving. Currently UNIMPLEMENTED

You can also use the dropdown Add joint component to add drives or limits to your joint. Limits let you reduce the permissible range of motion, and drives let you add spring and damper elements or a motor.

Articulations

Articulations are useful for creating hierarchical mechanisms such as a vehicle or a robot. You can add an ArticulationAPI (using Physics Properties / Add Prim Component ) either to a rigid body in a hierarchy or the parent of the first link. The graph of joints connecting bodies will be parsed starting at this body, and the parts will be simulated relative to one another, which is usually more accurate than conventional jointed simulation. The articulation has two important properties:

Attribute

Description

fixed base

the root of the articulation hierarchy becomes immovable

enable self collisions

cancels the default behavior of the parts of the hierarchy not colliding

Next, you should add an ArticulationJointAPI to every joint in the armature. This will make the joint become part of the articulation.

This API has an important field called articulationType, with the following values:

Value

Description

articulatedJoint

Connects two articulation links (rigid bodies) in hierarchy.

maximalJoint

Requests this joint to become a non-articulation joint.

maximalJoint is useful if you have a cycle of joints and you want to specify where to break the loop, since articulations have to be acyclic, as transforms are computed relative to a parent.

Character Controller

A character controller (CCT) is our name for a video game style movement controller that permits the player to move around a world without being able to go through walls.

The player is represented by a capsule shape, often a box or a capsule, so start by creating and selecting a Capsule primitive. Then press the Create CCT on Given Capsule Geom button in the CCT window. This will hide the capsule and give it CCT properties. You can now press the other button Reload Character Controllers/Cameras to populate the two drop down menus above. Here you can select a CCT to take control of when the Play button is pressed, and you can also select a camera to tie to this CCT, so that you can see a “first person” view. When you do both and press play, you can control the camera with the W A S D keys and right mouse drag to change the view direction. It should collide with physical objects as expected.

Physics Settings

The Physics > Settings window has some important opportunities to configure your simulation. The Update to USD and Reset simulation on stop control what exactly should happen when you press Play. Depending on the settings, the simulation results will either be written back to USD just like editing operations, or just rendered with no side effect. Reset on stop means Create reverts the state of the stage when Stop is pressed to just how it was when Play was pressed. This will also cause editing operations made during simulation to be lost!

Use fast cache is an internal performance optimization that avoids updating some internal data structures. If you run into any consistency issues it is a good idea to try again with this turned off.

Under the Simulator rollout you will find basic settings like the scale of your scene (which will have an effect on things like mass computations) and how many times the simulation should update per second. More steps per second usually means more robust physics. This can be further improved with more substeps at the cost of higher computational load. Generally smaller time steps are more beneficial than more substeps.

The number of simulation threads controls how many background threads are spawned and reserved for simulation.

Physics visualization

It is common practice to use low detail geometry for collisions and pretty high detail geometry for rendering. Unfortunately this means you will not see your collision geometry – and there are a large number of physical properties that have no visual manifestation at all – and it can be tricky to visually identify problems with the physics behavior of your scene.

The Physics > PhysX Debug Window is here to solve this problem. One of the most important diagnostics is right at the top: Step lets you advance your simulation one time step at a time, so you can closely observe problems that happen very quickly. Below is Create’s built in shape visualizer. This lets you display collision geometry as purple wireframes either for all or just selected geometry as soon as they are created.

This is in contrast to the Visualization base settings which only update during simulation. To use this, you need to enable it, and then enable individual visualization modes from the Visualization toggles list. This can not only show collision shapes, but also mass distributions, contact points and all sorts of other useful things. Arrows such as those used to display coordinate frames or velocities can be tuned in length using Visualization scale.

Using Rigid Body Physics (Video)

The fundamental type of simulation in physics is rigid body simulation. In Create it is possible to define rigid bodies and their properties through physics USD schema.

This videos demonstration shows how to use Basic Omniverse Rigid Body Physics.

../_images/main_report_problem.png

Destruction and Fracture

../_images/kit_physics_blast_beauty.png

The Blast fracture tool is a decimation utility that excels at shattering and breaking objects.

User Interface

../_images/kit_physics_blast_panel.png

Option

Effect

Num Voronoi Sites

The number of pieces in which to fracture the selected meshes.

Contact Threshold

The minimum contact impulse to trigger a contact event with a destructible.

Interior Material

The material to display on the newly created (interior) faces.

Physics Mode

The type of physics applied to the selected prim.

Fracture Selected

Fracture the selected mesh prim.

Combine Selected

Combines the selected mesh prims into a “multi-root” destructible.

Explode View Radius

When Not simulating, separates the chunks for inspection and/or selection.

View Layer(s)

Select which layer(s) to view while using the Explode View feature.

Recalculate Attachment

Search for nearby static or dynamic geometry and form bonds with that geometry.

Select Parent

Select the parent(s) of the currently selected chunk(s). Removes children from selection set.

Select Children

Select the children(s) of the currently selected chunk(s). Removes parents from selection set.

Reset Fracture Data

Destroys all fracture information, restores original mesh.

Damage Profile

Which damage program to run when a desrtructible actor receives a damage event.

Damage Amount

The base damage amount for damage calculations.

Damage Min Distance

The meaning of this depends on the damage profile (see below).

Damage Max Distance

The radius outside which no damage is applied.

Damage Impulse

The outward impulse applied to fractured pieces.

Impact Damage Scalar

A multiplier, contact impulses are multiplied by this amount to obtain a damage amount.

Max Contact Impulse

Applied to kinematic destructibles, limits the force applied to an impacting object.

Debug Visualization

Turn on destruction debug visualization for the selected prim or all prims with destruction data.

Important

Decimation has the potential to overwhelm computer resources and cause Create to crash unexpectedly. Use caution when increasing Number of Voronoi Sites.

Damage Profiles

Radial Damage (Falloff)

Simulates an explosion. Chunks/bonds within the damage range are damaged regardless of the graph topology. Full damage is done if the distance is between 0 and the min distance, no damage is done beyond the max distance. Between them, damage linearly decreases.

Radial Damage (Cutter)

Similar to Falloff, except damage inside the min distance is 0, in the range is the full damage amount, and beyond the max distance is 0.

Impact Spread

Simulates a physical impact. It assumes that position is somewhere on the chunk and looks for nearest chunk to this position and damages it. Then it does breadth-first support graph traversal. For damage falloff, distance is measured along the edges of the graph. That allows it to avoid damaging parts which are near in space but disjointed topologically. For example if you hit one column of an arc it would take much bigger max distance for damage to travel to the other column than in the simple radial damage. Damage falloff over distance is calculated the same way as radial falloff.

Tutorials

Getting Started

This tutorial shows initial setup:
  1. Navigate to Window > Extensions Manager

  2. Check-On “omni.blast”

  3. N.B. Using Blast with FastCache can lead to crashes. When using Blast, disable FastCache in the Physics Settings panel.

Once enabled, we create a rigid body and fracture it:
  1. Select the physics prim to fracture

  2. Locate and open the blast pane

  3. Adjust Blast settings as desired

  4. Click the “Fracture Selected” button to fracture it

  5. Scrub/adjust the explode view radius to review the fracture

Running the simulation (by pressing “Play”), the destructible falls to the ground and fractures due to impact damage.

Reset Fracture

Here we see how to undo a fracture operation:
  1. Select a mesh with Blast applied

  2. Click the Reset Fracture Data button

  3. Dialogue will warn of deletion permanency; agree to delete

In the video we change the Num Voronoi Sites number and re-fracture.

Multilevel Fracture

Here we see how to recursively fracture. Chunks of a fractured mesh may be broken down further:
  1. Select a mesh with Blast applied

  2. Adjust the explode view radius to make chunk selection easy

  3. Select the desired chunks to fracture further

  4. Adjust the Num Voronoi Sites to the desired number. (Each chunk will be split into that many pieces.)

  5. Click the “Fracture Selected” button to fracture the selected chunks

Kinematic Destructible

In this tutorial we see a way to keep a destructible “static” (in this case, kinematic) before it is fractured:
  1. Select a physics prim

  2. Under the PhysX Properties pane, check kinematicEnabled

  3. Click the “Fracture Selected” button to fracture the prim as usual

  4. Running the simulation (pressing the “Play” button), the prim stays suspended in mid-air, as it is kinematic

  5. When fractured, the pieces become dynamic

Static Attachment

This tutorial shows another way of creating a “static” destructible, by emulating an attachment to the static world:
  1. Create a destructible prim in the usual way (see above)

  2. Place the destructible prim adjacent to (or overlapping) a static collision mesh

  3. Press the Recalculate Attachment button to form bonds between the destructible and nearby static geometry

When simulating, the bonds formed keep the destructible “static” (kinematic). When fractured, chunk islands that are not connected via bonds to static geometry become dynamic bodies. The chunks that remain connected to static geometry via bonds remain kinematic.

Dynamic Attachment

Here we see how to turn a part of a rigid body into a destructible. If the rigid body consists of multiple meshes, we may select one and make it destructible:
  1. Select the rigid body mesh to make destructible

  2. Click the “Fracture Selected” button to fracture the mesh as usual

  3. Press the Recalculate Attachment button. Bonds will be formed with any adjacent or overlapping collision geometry from the same rigid Body

When simulating, the destructible mesh will move rigidly with its parent physics. When fractured, chunk islands that are not connected via bonds to the parent physics geometry become separate dynamic bodies. The chunks that remain connected to the parent physics geometry via bonds remain rigidly connected to the physics body.

Note, if no bonds were formed (because there was no adjacent or overlapping collision geometry from the parent rigid body), then all chunk islands become dynamic when the destructible is fractured.

Note

If Shift + Click does not “Explode” Mesh, Try increasing Damage Amount, Damage Radius and/or Explosive Impulse. Changing Material(s) requires re-fracturing Physics Properties of the Source Asset propogate to the fracutred elements.

../_images/main_report_problem.png

Fluid Dynamics

Flow is an Eulerian fluid simulation for smoke and fire, leveraging a sparse voxel grid for unbounded simulation domain.

Using Flow

Enabling Flow

Open the Extension Manager (Window > Extension Manager)

FlowExtensionManager

In the Extension Manager, enable the “omni.flowusd” extension

FlowUsdExtension

Enable Flow in Render Settings

FlowRenderSettings

Basic Simulation

Create an Xform

CreateXform

In the Flow menu, Add Sphere Emitter as a child to that Xform

AddSphereEmitter

At the root of the stage, Add Simulate Settings, Offscreen Settings and Render Settings.

AddSimSetting

Press play, verify smoke simulates

smoke

Templates

Because of the wide variety of effects one can achieve from Flow, it is often convenient to have a working starting point from which to then adjust to match your needs. Especially when starting out, users are encoraged to begin with one of the presets as they are full working simulations and can be altered to suit the specific use case.

Understanding Flow

Cell Size

Cell Size has one of the most significant impacts on both appearance and performance. Keep in mind cutting cell size in half is an 8x increase in cells and as a result simulation time.

Effect Lifetime

The damping/fade on advection largely controls effect lifetime.

Effect Scale

Vorticity forceScale has a significant impact on perceived scale. Higher forceScale tends to make effects appear larger.

Combustion Modeling

Default Flow today includes a simple combustion model. Settings like buoyancyPerBurn help create mushroom cloud motion expected from explosions.

Layers

Layers are a relatively new and experimental feature. Right now, they are controlled with raw integers acting as an enum. Later, these might get auto assigned based on a path or string name. Layers allow multiple active simulation instances, while recycling the same memory pool and compute dispatch. This makes multiple simulations cost nearly the same as a single simulation, for a given number of active blocks.

Velocity

With velocity, more is not always more. This simulation is based on stable fluids, where high velocities don’t necessarily behave as expected, but the simulation does not explode. Coarser cell size will effectively behave better will higher world scale velocities. Support for velocity substepping and overall shorter simulation steps are exposed, that improve high velocity behavior with a performance cost.

Rendering

Rendering today uses the Flow reference implementation. Future versions will likely lean on native volume support in the RTX renderer. Basic Flow rendering provides a colormap to map temperature to color/alpha for fire/smoke. Also included is self shadowing and some basic modulated shadows.

Collision

Collision support today is very limited. However emitters can be adapted for this purpose. Set allocationScale to 0.0, since collision only needs to be active when the simulation is visibly active. Set temperature/fuel/burn/smoke/divergence couple rates to zero, as we only need to control velocity. Set target velocity to (0, 0, 0). Set physicsVelocityScale to 1.0 for moving objects, to include body velocity. Set coupleRateVelocity to 120 or higher, to drive velocity to body velocity within a single frame. Set applyPostPressure to true, as this guarantees velocity at the end of the frame will match body velocity.

Settings

Simulate Settings

Property

Result

layer

Simulation with these settings will go active for this integer layer ID. Only one simulate
settings per layer ID is supported.

densityCellSize

Size of density cells in world units. By default velocity cell size is twice density cell size.

enableSmallBlocks

Use 16x8x8 density cell blocks instead of the default 32x16x16

forceClear

Kills all active block allocations

forceDisableEmitters

Disable all emitters in this layer

stepsPerSecond

Simulation update rate

maxStepsPerSimulate

Limit on steps per frame to avoid excessive steps when application is running slow.

enableVariableTimeStep

Instead of fixed deltaTime steps, take maxStepsPerSimulate steps each frame.

velocitySubSteps

Higher values improve behavior with high speed effects, at the cost of performance.

advection

See Advection section

vorticity

See Vorticity section

summaryAllocate

See SummaryAllocate section

Advection

Property

Result

velocity

Parameters for advection of velocity channel. See Advection Channel section

temperature

Parameters for advection of temperature channel. Set Advection Channel section

fuel

Parameters for advection of fuel channel. Set Advection Channel section

smoke

Parameters for advection of smoke channel. Set Advection Channel section

ignitionTemp

Minimum temperature for combustion.

burnPerTemp

Rate of burn relative to temperature. Higher burn values affect fuel consumption and
divergence (expansion) terms.

fuelPerBurn

Fuel consumed relative to burn amount. Lower values will make a given amount of fuel
last longer.

tempPerBurn

Temperature increase relative to burn amount.

smokePerBurn

Smoke increase relative to burn amount.

divergencePerBurn

Expansion relative to burn amount. Units comparable to velocity in terms of scale.
Higher values produce visible expansion, but can remove detail.

buoyancyPerTemp

Upward force relative to temperature. Higher values help produce mushroom effects.

buoyancyPerSmoke

Buoyant force per unit smoke, default 0.0

buoyancyMaxSmoke

Smoke clamp value applied before computing smoke buoyancy, default 1.0

coolingRate

Temperature fade, applied on a per cell level. (Not conduction/convection.)

gravity

Used to determine the ‘up’ direction for buoyancy.

globalFetch

Improves advection quality for high velocities, with some increase in runtime cost.
(Can remove some banding artifacts)

Advection Channel

Property

Result

secondOrderBlendThreshold

Minimum value to apply second order correction. Reduces simulation cost for cells
near zero, with minimal/zero visual artifacts.

secondOrderBlendFactor

Second order correction factor. Value range is 0.0 to 1.0. 0.5 is generally a
safe default. Higher values increase the sharpness, but comes with potentially
banding artifacts. Use extra caution with velocity, where effects are even
more pronounced.

damping

Reduce channel proportional to current value. Valid range is 0 to 1, where 1
takes the value to 0 immediately.

fade

Reduce channel at a constant rate per second. Valid range is 0 to infinity
effectively.

Vorticity

Property

Result

Vorticity forceScale

Control intensity of effect

velocityMask

Velocity log mask, works together with velocityLogScale. Makes local linear
velocity a requirement for forces to be applied. The log part makes the force
applied with respect to velocity a diminishing return to avoid instability.

constantMask

Allows force to be applied without respect to local velocity.

densityMask

Allows force to be applied relative to divergence (Parameter name
should be fixed.)

velocityLogScale

This primarily exists to allow rescaling of Flow effects to different
coordinate systems.
Math: velocityMask * log2(velocityLogScale * speed + 1.0)

velocityLinearMask

Makes force directly proportional to local velocity
Math: velocityLinearMask * speed

SummaryAllocate

Property

Result

smokeThreshold

Minimum smoke to keep a block active.

speedThreshold

Minimum speed to keep a block active, given
speedThresholdMinSmoke is satisfied.

speedThresholdMinSmoke

Minimum smoke value for speedThreshold to apply.

Offscreen Settings

Property

Result

Layer

Layer ID to apply these settings to

shadow

Self shadow settings. See Shadow section

colormap

Describes how temperature/smoke map to color.
See Colormap section

debugVolume

Velocity visualization. See DebugVolume section

Shadow

Property

Result

lightDirection

Directional light. Points to light.

lightPosition

Point light position.

isPointLight

If true, point light, else directional light.

attenuation

Rate of light blockage. Higher values increase self shadow effect.

stepSizeScale

Ray march step size relative to cell size. Higher values increase
quality and performance cost.

stepOffsetScale

Ray march offset to avoid a cell shadowing itself.

minIntensity

Provide ambient level

numSteps

Number of steps per self shadow ray, divide by 2 when
coarsePropagate is enabled.

coarsePropagate

Compute shadows at 2x2x2 coarser grid. Provides good
quality at a much lower runtime cost.

Colormap

Property

Result

resolution

Number of texels in colormap

xPoints

X coordinates of control points, maps to temperature. Valid over 0 to 1

rgabPoints

RGBA values of control points, RGB can be over 1.0 for HDR effects.

DebugVolume

Property

Result

enableSpeedAsTemperature

Write speed value to temperature channel, to visualize in ray march.

enableVelocityAsDensity

Write abs() of velocity channels to density xyz to visualize in ray march.

velocityScale

Scale applied to velocity to control brightness for ray march result.

Render Settings

Property

Result

layer

Layer ID to apply these settings to

rayMarch

See RayMarch section

RayMarch

Property

Result

enableBlockWireframe

Visualizes active blocks for debug purposes

enableRawMode

If true, do not apply colormap, pass raw density xyzw as color

attenuation

Rate of light blockage. Higher values make the volume look more opaque

stepSizeScale

Ray march step size relative to cell size. Higher values increase
quality and performance cost.

shadowFactor

The degree to which the z shadow channel scales the RGB channels from
the colormap. 1.0 is default. 0.0 disables self shadowing effectively.

modulatedShadow

Simple shadow computed based on scene depth. See ModulatedShadow section.

ModulatedShadow

Property

Result

enabled

If true, compute and apply modulated shadows.

alphaScale

Alpha scale for applying shadows. Higher values make darker shadows.

lightDirection

Directional light. Points to light.

lightPosition

Point light position.

isPointLight

If true, point light, else directional light.

Emitter Sphere

Property

Result

enabled

Boolean to enable/disable emitter

position

World position of sphere

layer

Layer ID of simulation this emitter effects

radius

World space radius of sphere

allocationScale

1.0 allocates blocks needed to contain sphere. 0.0 disables allocation.
Values higher than 1.0 can be used to add additional padding.

velocity

Target velocity that the emitter moves grid velocity toward.

divergence

Target divergence (expansion) that the emitter moves grid divergence toward.

temperature

Target temperature that the emitter moves grid temperature toward.

fuel

Target fuel that the emitter moves grid fuel toward.

burn

Target burn that the emitter moves grid burn toward.

smoke

Target smoke that the emitter moves grid smoke toward.

coupleRateVelocity

Rate at which the grid velocity moves toward the emitter target velocity.
A value of 120 will typically make the change instantaneous.
This is useful for collision, but lower values like 1 blend more naturally

coupleRateDivergence

Rate at which the grid divergence moves toward the emitter target divergence .
A value of 120 will typically make the change instantaneous.
Lower values like 1 blend more naturally with the simulation

coupleRateTemperature

Rate at which the grid temperature moves toward the emitter target temperature.
A value of 120 will typically make the change instantaneous.
Lower values like 1 blend more naturally with the simulation

coupleRateFuel

Rate at which the grid fuel moves toward the emitter target fuel.
A value of 120 will typically make the change instantaneous.
Lower values like 1 blend more naturally with the simulation

coupleRateBurn

Rate at which the grid burn moves toward the emitter target burn.
A value of 120 will typically make the change instantaneous.
Lower values like 1 blend more naturally with the simulation

coupleRateSmoke

Rate at which the grid smoke moves toward the emitter target smoke.
A value of 120 will typically make the change instantaneous.
Lower values like 1 blend more naturally with the simulation

physicsVelocityScale

If set to 1.0, the body velocity will be added to the target velocity.
This is useful for collision effects, where the body velocity
and grid cell velocity should align.

applyPostPressure

If true, apply velocity after pressure solve. This is useful
for collision, as it allows hard enforcement of velocity inside
moving bodies.

multisample

Test sphere overlap at 8 locations instead of 1

Emitter Box

Property

Result

enabled

Boolean to enable/disable emitter

layer

Layer ID of simulation this emitter effects

halfSize

Half of box width/height/depth in local units

allocationScale

1.0 allocates blocks needed to contain sphere. 0.0 disables allocation.
Values higher than 1.0 can be used to add additional padding.

velocity

Target velocity that the emitter moves grid velocity toward.

divergence

Target divergence (expansion) that the emitter moves grid divergence toward.

temperature

Target temperature that the emitter moves grid temperature toward.

fuel

Target fuel that the emitter moves grid fuel toward.

burn

Target burn that the emitter moves grid burn toward.

smoke

Target smoke that the emitter moves grid smoke toward.

coupleRateVelocity

Rate at which the grid velocity moves toward the emitter target velocity.
A value of 120 will typically make the change instantaneous.
This is useful for collision, but lower values like 1 blend more
naturally with the simulation

coupleRateDivergence

Rate at which the grid divergence moves toward the emitter target divergence.
A value of 120 will typically make the change instantaneous.
This is useful for collision, but lower values like 1 blend more
naturally with the simulation

coupleRateTemperature

Rate at which the grid temperature moves toward the emitter target temperature.
A value of 120 will typically make the change instantaneous.
This is useful for collision, but lower values like 1 blend more
naturally with the simulation

coupleRateFuel

Rate at which the grid fuel moves toward the emitter target fuel.
A value of 120 will typically make the change instantaneous.
This is useful for collision, but lower values like 1 blend more
naturally with the simulation

coupleRateBurn

Rate at which the grid burn moves toward the emitter target burn.
A value of 120 will typically make the change instantaneous.
This is useful for collision, but lower values like 1 blend more
naturally with the simulation

coupleRateSmoke

Rate at which the grid smoke moves toward the emitter target smoke.
A value of 120 will typically make the change instantaneous.
This is useful for collision, but lower values like 1 blend more
naturally with the simulation

physicsVelocityScale

If set to 1.0, the body velocity will be added to the target velocity.
This is useful for collision effects, where
the body velocity and grid cell velocity should align.

applyPostPressure

If true, apply velocity after pressure solve. This is useful for
collision, as it allows hard enforcement of velocity inside moving bodies.

multisample

Test sphere overlap at 8 locations instead of 1

Emitter Point

Property

Result

enabled

Boolean to enable/disable emitter

layer

Layer ID of simulation this emitter effects

allocateMask

Default allocation behavior. If true and allocateMasks is empty, all points will trigger allocation.

velocity

Target velocity that the emitter moves grid velocity towards if pointVelocities array does not specify.

divergence

Target divergence that the emitter moves grid divergence towards if pointDivergences array does not specify.

temperature

Target temperature that the emitter moves grid temperature towards if pointTemperatures array does not specify.

fuel

Target fuel that the emitter moves grid fuel towards if pointFuels array does not specify.

burn

Target burn that the emitter moves grid burn towards if pointBurns array does not specify.

smoke

Target smoke that the emitter moves grid smoke towards if pointSmokes array does not specify.

coupleRateVelocity

Default rate at which the grid velocity moves toward the emitter target velocity.
A value of 120 will typically make the change instantaneous.
This is useful for collision, but lower values like 1 blend more
naturally with the simulation

coupleRateDivergence

Default rate at which the grid divergence moves toward the emitter target divergence .
A value of 120 will typically make the change instantaneous.
This is useful for collision, but lower values like 1 blend more
naturally with the simulation

coupleRateRateTemperature

Default rate at which the grid temperature moves toward the emitter target temperature.
A value of 120 will typically make the change instantaneous.
This is useful for collision, but lower values like 1 blend more
naturally with the simulation

coupleRateFuel

Default rate at which the grid fuel moves toward the emitter target fuel.
A value of 120 will typically make the change instantaneous.
This is useful for collision, but lower values like 1 blend more
naturally with the simulation

coupleRateBurn

Default rate at which the grid burn moves toward the emitter target burn.
A value of 120 will typically make the change instantaneous.
This is useful for collision, but lower values like 1 blend more
naturally with the simulation

coupleRateSmoke

Default rate at which the grid smoke moves toward the emitter target smoke.
A value of 120 will typically make the change instantaneous.
This is useful for collision, but lower values like 1 blend more
naturally with the simulation

pointPositions

Array of local space positions. Determines total point count.

pointAllocateMasks

Optional array of allocate settings per point.

pointVelocities

Array of target velocities for each position.

pointDivergences

Array of target divergences for each position.

pointTemperatures

Array of target temperatures for each position.

pointFuels

Array of target fuels for each position

pointBurns

Array of target burns for each position

pointSmokes

Array of target smokes for each position

pointCoupleRateVelocities

Array of couple rate velocities for each position.
A value of 120 will typically make the change instantaneous.
This is useful for collision, but lower values like 1 blend more naturally with the simulation

pointCoupleRateDivergences

Array of couple rate divergences for each position.
A value of 120 will typically make the change instantaneous.
This is useful for collision, but lower values like 1 blend more naturally with the simulation

pointCoupleRateTemperatures

Array of couple rate temperatures for each position.
A value of 120 will typically make the change instantaneous.
Lower values like 1 blend more naturally with the simulation

pointCoupleRateFuels

Array of couple rate fuels for each position.
A value of 120 will typically make the change instantaneous.
Lower values like 1 blend more naturally with the simulation

pointCoupleRateBurns

Array of couple rate burns for each position.
A value of 120 will typically make the change instantaneous.
Lower values like 1 blend more naturally with the simulation

pointCoupleRateSmokes

Array of couple rate smokes for each position.
A value of 120 will typically make the change instantaneous.
Lower values like 1 blend more naturally with the simulation

applyPostPressure

If true, apply velocity after pressure solve.
This is useful for collision, as it allows hard enforcement of velocity inside moving bodies.

Emitter Texture

Property

Result

enabled

Boolean to enable/disable emitter

position

World space position

layer

Layer ID of simulation this emitter effects

halfSize

Half of box width/height/depth in world units

allocationScale

1.0 allocates blocks needed to contain sphere. 0.0 disables allocation. Values higher than 1.0 can be used to add
additional padding.

velocity

Default target velocity that the emitter moves grid velocity toward.

divergence

Default target divergence (expansion) that the emitter moves grid divergence toward.

temperature

Default target temperature that the emitter moves grid temperature toward.

fuel

Default target fuel that the emitter moves grid fuel toward.

burn

Default target burn that the emitter moves grid burn toward.

smoke

Default target smoke that the emitter moves grid smoke toward.

coupleRateVelocity

Default rate at which the grid velocity moves toward the emitter target velocity.
A value of 120 will typically make the change instantaneous.
This is useful for collision, but lower values like 1 blend more
naturally with the simulation

coupleRateDivergence

Default rate at which the grid divergence moves toward the emitter target divergence .
A value of 120 will typically make the change instantaneous.
This is useful for collision, but lower values like 1 blend more
naturally with the simulation

coupleRateRateTemperature

Default rate at which the grid temperature moves toward the emitter target temperature.
A value of 120 will typically make the change instantaneous.
This is useful for collision, but lower values like 1 blend more
naturally with the simulation

coupleRateFuel

Default rate at which the grid fuel moves toward the emitter target fuel.
A value of 120 will typically make the change instantaneous.
This is useful for collision, but lower values like 1 blend more
naturally with the simulation

coupleRateBurn

Default rate at which the grid burn moves toward the emitter target burn.
A value of 120 will typically make the change instantaneous.
This is useful for collision, but lower values like 1 blend more
naturally with the simulation

coupleRateSmoke

Default rate at which the grid smoke moves toward the emitter target smoke.
A value of 120 will typically make the change instantaneous.
This is useful for collision, but lower values like 1 blend more
naturally with the simulation

textureWidth

Width in texels of texture data

textureHeight

Height in texels of texture data

textureDepth

Depth in texels of texture data

textureVelocities

Array of target velocities for each texel.
arrayIdx = (texelIdx.z * textureHeight + texelIdx.y) * textureWidth + texelIdx.x

textureDivergences

Array of target divergences for each texel.
arrayIdx = (texelIdx.z * textureHeight + texelIdx.y) * textureWidth + texelIdx.x

textureTemperatures

Array of target temperatures for each texel.
Math: arrayIdx = (texelIdx.z * textureHeight + texelIdx.y) * textureWidth + texelIdx.x

textureFuels

Array of target fuels for each texel.
Math: arrayIdx = (texelIdx.z * textureHeight + texelIdx.y) * textureWidth + texelIdx.x

textureBurns

Array of target burns for each texel.
Math: arrayIdx = (texelIdx.z * textureHeight + texelIdx.y) * textureWidth + texelIdx.x

textureSmokes

Array of target smokes for each texel.
Math: arrayIdx = (texelIdx.z * textureHeight + texelIdx.y) * textureWidth + texelIdx.x

textureCoupleRateVelocities

Array of couple rate velocities for each texel.
A value of 120 will typically make the change instantaneous.
This is useful for collision, but lower values like 1 blend more naturally with the simulation
Math: arrayIdx = (texelIdx.z * textureHeight + texelIdx.y) * textureWidth + texelIdx.x

textureCoupleRateDivergences

Array of couple rate divergences for each texel.
A value of 120 will typically make the change instantaneous.
This is useful for collision, but lower values like 1 blend more naturally with the simulation
Math: arrayIdx = (texelIdx.z * textureHeight + texelIdx.y) * textureWidth + texelIdx.x

textureCoupleRateTemperatures

Array of couple rate temperatures for each texel.
A value of 120 will typically make the change instantaneous.
Lower values like 1 blend more naturally with the simulation
Math: arrayIdx = (texelIdx.z * textureHeight + texelIdx.y) * textureWidth + texelIdx.x

textureCoupleRateFuels

Array of couple rate fuels for each texel.
A value of 120 will typically make the change instantaneous.
Lower values like 1 blend more naturally with the simulation
Math: arrayIdx = (texelIdx.z * textureHeight + texelIdx.y) * textureWidth + texelIdx.x

textureCoupleRateBurns

Array of couple rate burns for each texel.
A value of 120 will typically make the change instantaneous.
Lower values like 1 blend more naturally with the simulation
Math: arrayIdx = (texelIdx.z * textureHeight + texelIdx.y) * textureWidth + texelIdx.x

textureCoupleRateSmokes

Array of couple rate smokes for each texel.
A value of 120 will typically make the change instantaneous.
Lower values like 1 blend more naturally with the simulation
Math: arrayIdx = (texelIdx.z * textureHeight + texelIdx.y) * textureWidth + texelIdx.x

applyPostPressure

If true, apply velocity after pressure solve.
This is useful for collision, as it allows hard enforcement of velocity inside moving bodies.
../_images/main_report_problem.png

Vehicle Dynamics

The Vehicle Dynamics extension provides tools for creating vehicle simulations that include tire, engine, clutch, transmission and suspension models.

Using Vehicle Dynamics

Enabling Vehicle Dynamics

Open the Extension Manager Window > Extension Manager

VehicleExtensionManager

In the Extension Manager, enable the “omni.physx.vehicle” extension

VehicleExtension

Vehicle Dynamics Introduction

The Vehicle Extension provides some sample scenes that can be loaded quickly to see how the vehicle drives and works in Create.

Open the Physics Demo Scenes Physics > Demo > PhysX

VehiclePhysicsDemoPhysx

In the Physics Demo Scenes Tab, click on the Vehicle Samples list to show the list of available samples.

VehicleSamples

As an introduction, select the Vehicle sounds sample and click Load scene.

VehicleLoadScene

If you have a gamepad connected to your PC, and would like to drive the vehicle with it, click on the settings gear in the top left corner of the Viewport window. Then, uncheck the Gamepad Camera Control setting. This allows the gamepad to control the vehicle, instead of the camera. If you would prefer to control the vehicle with the keyboard arrow keys, this step can be skipped.

VehicleGamepad

Add a camera that can follow the vehicle from a chase vehicle. Click on the Stage Tab, expand the World list, and select the Vehicle itself.

VehicleStage

Now, click the PhysX Vehicle Tab and press the Add Follow Camera button.

VehicleAddFollowCameraButton

A camera will appear in the Viewport. To view the scene through that camera, click on the camera icon in the top left corner of the Viewport window, click on the Camera button and select the VehicleFollowCamera.

VehicleSelectFollowCamera

This demo plays engine and tire sounds interactively as you control the vehicle. To hear it, make sure your PC audio is not muted and is set to a reasonable volume. Press the Play button on the left side of Create.

VehiclePlay

If you are using a gamepad, use the right trigger to accelerate, the left trigger to brake and the left analog joystick to steer the vehicle left and right. If you are using a keyboard, use the up arrow key to accelerate, the down arrow key to brake and the left and right arrow keys to steer the vehicle. Press the Stop button to end the simulation.

Creating a Vehicle Using the Vehicle Wizard

Introduction

The physical simulation of a vehicle requires many components and settings that must be created and tuned. To make the process a bit easier, Create provides a Vehicle Wizard that asks for some initial parameters as inputs and creates a working vehicle simulation. If the first vehicle created has to be changed, it can be deleted and the Vehicle Wizard settings can be adjusted to try again.

Alternatively, Create provides a couple of Vehicle Samples in the Physics Demo Scenes that can be used as a starting point for a vehicle simulation. One uses a Basic Drive setup and the other uses a Standard Drive setup. The differences between these two types are discussed in the Vehicle Wizard Basic Page documentation, below.

Authoring the Vehicle’s Rendered Mesh

The Vehicle Wizard and the Vehicle Samples create a vehicle out of primitive geometric shapes, a box for the chassis and four cylinders for the wheels. An artist authored vehicle mesh used for rendering can then be linked to these transforms and animated.

VehicleGeometricPrimitives

The physics representation created by Create and the rendered vehicle mesh should be authored in the same coordinate system and units. This will avoid the need to add additional rotations or scale to make the two representations match. The Vehicle Samples are hard coded to use the Y axis as the up axis. However, the Vehicle Wizard can be configured to match any coordinate system. Prior to using the Vehicle Wizard, open the Edit > Preferences window and select the Default Up Axis to Y or Z to match the coordinate system used to author the rendered vehicle.

VehicleEditPreferences

There are many different types of vehicle suspensions and there are several ways to articulate them. A full simulation of the suspension using rigid-bodies and constraints is a separate topic and will not be discussed here. Simulating the wheels and then animating the suspension pieces to maintain a connection between the wheels and the chassis is a simpler, faster, technique. Animating the suspension in this way can also be accomplished in different ways depending on the need for accuracy.

The easiest way to animate the tires on the rendered vehicle is to connect them to the tires animated by the physics simulation. (Refer to Animating the Wheels to see how to do this.) The drawback of this method is that the suspension parts themselves will be rigidly connected to the chassis and will not animate. This is useful if the vehicles are not the primary focus of the project. If this technique is suitable, the only parts of the rendered mesh that must be separated from the original mesh are the rotating parts of the wheel and tire. All the other parts can remain part of the chassis mesh.

For a higher fidelity animation of the vehicle suspension, the mesh will need to be further subdivided. The rendered mesh will need to be broken apart into parts of the wheel that steer and move up and down with the suspension, but do not rotate and parts of the wheel that do rotate. Next, separate all the suspension parts that connect the non-rotating wheel parts to the chassis. Do this for each wheel. Although there are many different suspension configurations, the following primitive hierarchy should work for most:

  • Chassis (All vehicle parts that are rigidly connected to the body of the vehicle.)

    • FrontLeftSuspension (All non-rotating parts that steer and move vertically as the suspension compresses.)

      • FrontLeftWheel (All parts of the wheel and tire that rotate.)

Duplicate this hierarchy for each of the wheels and tires.

The Wheel and Tire transforms should be positioned in the exact center of rotation for each wheel. The Suspension Part transforms should be centered on their axes of rotation if they rotate.

It is recommended, but not required, that the vehicle mesh is loaded into the stage prior to using the Vehicle Wizard so that all primitives are on the same layer. This makes it possible to simply drag and drop the appropriate mesh pieces onto the appropriate physics vehicle hierarchy nodes. If the Vehicle Wizard is used first, the vehicle mesh may end up being referenced on a different layer. This prevents it from being separated and linked to different pieces of the physics hierarchy.

The next step is to create or load the physics representation of the vehicle by using the Vehicle Wizard or loading one of the Vehicle Samples. Refer to the Animating the Vehicle’s Rendered Mesh section, below, for the next steps to connecting the rendered mesh to the vehicle’s physics simulation.

Vehicle Wizard Description

The Vehicle Wizard can be opened through the Physics > Add > Vehicle menu command.

VehicleAdd

The Vehicle Wizard contains three pages. The first asks for the basic dimensions and configuration of the vehicle, the second sets the dimensions of the tires and suspension settings. The last page provides a check list of optional Next Steps to complete the set up of the vehicle and its physics.

The vehicle created by the wizard will be oriented according to Create’s coordinate frame. If Z-up is selected, the positive X or Y axes can be the forward direction. If Y-up is selected, the X or Z axes can be forward. The Vehicle Wizard will create a primitive named VehicleGlobalSettings that reflects this. However, if VehicleGlobalSettings already exists on the stage, its up axis and forward axis will be used to orient the new vehicle.

Basic Page

VehicleBasicPage

In the Chassis Box panel, enter the Width, Length and Height in the same units that are being used in Create to model the world. These dimensions will be used to create a collision box that should contain most of the vehicle mesh geometry and will also be used to compute the mass distribution, or moments of inertia, of the vehicle. The collision box that is created by the wizard can be deleted and replaced with a more form fitting representation later, if desired. However, these inputs are still required to compute the vehicle’s basic mass properties.

Enter the weight of the vehicle in the Mass edit box in kilograms.

Position the center of the chassis box by entering the X, Y and Z positions in the appropriate fields. The forward direction of the vehicle can be selected from the Forward Axis drop down list. If the VehicleGlobalSettings prim exists on the stage, the Forward Axis drop down will be disabled and the VehicleGlobalSettings forward axis will be displayed. If a forward direction was not previously selected, the available options will be presented. For a Y up axis, the X and Z options will be available. For a Z up axis, X and Y can be selected.

An option to automatically fill in all of these settings is available by selecting a set of prims from the stage that represent the chassis and then pressing the Scan button. The Vehicle Wizard will fit an axis aligned bounding box to the selected prims and fill in all of the Chassis Box settings. The Mass edit box is computed using a constant density of 120 kg per cubic meter, multiplied by the volume of the bounding box. The Forward Axis is set assuming the longest side of the box is the length. Any of the automated entries can be adjusted after the scan is complete. Prims have a purpose that describes what they are used for, such as render, guide, default and proxy. Only render and default prims are scanned. Also, only geometric meshes and shapes can be used to fit a bounding box.

The Drive panel asks for one of three methods to propel the vehicle: Standard, Basic or None.

The Number of Axles edit box sets the number of tires on the vehicle. The tire settings are tuned on the next page.

Press the Next button to access these settings. Alternatively, the Create button can be pressed to use the Axle Page’s default settings to create the vehicle. Press Reset at any time to reset the settings on the Basic page to their default values.

Property

Description

Width

The lateral dimension of the vehicle chassis in world units

Length

The longitudinal dimension of the vehicle chassis in world units

Height

The vertical dimension of the vehicle chassis in world units

Mass

The weight of the entire vehicle in kg

X

The world X position of the center of the chassis in world units

Y

The world Y position of the center of the chassis in world units

Z

The world Z position of the center of the chassis in world units

Forward Axis

The forward direction of the vehicle

Scan Button

Computes an axis aligned bounding box around the selected prims and fills in all of the previous
settings automatically. The dimensions, mass and position can be adjusted after the scan is complete.

Type

Selects which propulsion model is used to generate tire torques (Standard, Basic, None)

Horsepower

For the Standard and Basic drive type, specifies how much power the engine can generate at its peak

Number of Gears

For the Standard drive type, specifies the number of gears the transmission has.

Number of Axles

Specifies the number of pairs of tires the vehicle has.

Next Button

Go to the Axles page

Create Button

Create a vehicle simulation using the current settings

Reset Button

Reset the Basic page properties to their default values

Standard Drive

The Standard drive type utilizes an engine and transmission to transfer torque to the driven tires. When using this Drive Type, enter the maximum engine Horsepower and the Number of Gears in the transmission.

The maximum engine RPM is initially set to 6000 RPM and the peak engine Horsepower is used to set the maximum horsepower in the following horsepower (HP) versus engine RPM curve:

VehicleEngineGraph

This power curve outputs peak horsepower at around 2000 RPM and drops off to 80% at engine idle and max RPM. This curve is not very realistic, but it generates more power at idle for better acceleration from rest.

The Number of Gears specify how many gears are in the transmission. The top gear is always 1:1 and the 1st gear ratio is set to the same value as the number of gears, 5:1 in a transmission with 5 gears, for example. The remaining gears evenly reduce the gear ratios between the 1st gear and the top gear. The final gear ratio is set to 4:1.

Gears scale the torque generated by the engine before it is applied to the tires. However, the higher the gear ratio, the sooner the transmission must shift up to the next gear before the engine reaches its maximum RPM. Heavier vehicles require higher gear ratios to generate more tire torque to accelerate but require additional gears and more time shifting to compensate.

The vehicle’s top speed will be determined by the Horsepower setting, while the vehicle’s acceleration profile will be controlled by the Number of Gears and Horsepower setting. If increasing the Horsepower does not increase the vehicle acceleration, then it is likely that the driven tires are spinning or burning out. To further increase the vehicle acceleration, the tire friction will need to be increased.

Basic Drive

The Basic drive type works by simply setting a maximum torque that is applied to the driven tires. No engine or transmission is created. Specify the maximum torque in the Horsepower edit box. The torque is scaled by the amount of throttle applied. The input device is also used to control the steer angle of the tires that steer. This Drive Type is useful for simulating electric vehicles.

No Drive (None)

When the None drive type is selected, no tire torques are passed to the tires by the vehicle. The tire torques and steer angles are set manually, instead. This allows customized user control of each tire independently. This can be useful for robotics applications, for example, where tires may be rotated in opposite directions to spin the robot in place.

Axles Page

VehicleAxlesPage

The Axles panel is used to specify which tires can steer in the Standard and Basic drive types and how much those tires steer. Tire torques are passed to all the tires that have the Driven check box selected. These settings are disabled for the, None drive type. Check the front axle for front wheel drive, check the rear axle for rear wheel drive, or check both axles for all wheel drive.

The Weight Distribution edit box specifies the percentage of the vehicle weight that rests on each axle. Best results are observed when the weight is evenly distributed, with slight adjustments. The percentages should all sum to 100%, but if they do not, each percentage will be normalized.

The Suspension Damping is used to control the bounce of the vehicle after it is disturbed, like going over a bump. A normal value of 0.3 is the default. This setting causes the vehicle to bounce once before settling. Higher values damp out oscillations faster. A setting of 0.7 causes the vehicle to settle without a single oscillation. For a bouncy ride, try settings between 0.1 and 0.3.

Scan Selected Prims buttons labeled Left and Right are provided to measure and automatically fill in the Radius, Width and Mass settings for each of the tires scanned. Just like the chassis box on the Basic Page, only render and default purpose prims are scanned and only geometric meshes and shapes can be used to fit a bounding box. Once a tire is scanned, its dimensions will appear below the Default wheel settings in the Wheels panel.

Inside the Wheels panel on the Axles page, select the tire Tire Type to use. The racing Slicks are stickiest on smooth surfaces. Summer tires provide a good grip on smooth, dry surfaces while All Season tires have the least grip on smooth, dry surfaces. The Enable Collisions check box is provided to generate collision objects for the tires themselves. This is useful for open wheeled vehicles, for example. However, if the chassis collision box encloses the tires, performance can be improved by disabling the tire collisions.

The Default tire Radius and Width, entered in the same units used to specify the chassis dimensions, are used to set the size of the tire used in the tire physics and tire collision detection. The Mass of the wheel, tire and all of the suspension components that are attached to the bottom of the suspension spring, referred to as the, “unsprung” mass of the vehicle. Any wheels that were scanned in the Axles panel will be presented below the Default settings. Any wheels that are not scanned will used the defaults.

VehicleAxlesPageWithWheels

Press, the Back button to re-adjust the Basic page settings. Changing the number of axles will reset this page. Press the Create button to create the vehicle and its components. Press the Next button to read the check list on the Next Steps page, and press the Reset button to reset the settings on the Axles page to their default values.

Property

Description

Steer Angle

The maximum angle the tire can rotate to one side, in degrees.

Driven

When checked, the tires on this axle receive a drive torque in the Standard or Basic drive types.

Weight Distribution

Specifies the percentage of the vehicle weight supported by this axle. The percentages should sum
to 100% but will be normalized if they do not.

Suspension Damping

The “damping ratio” of the shock absorbers, from 0 to 1. A value of 0.3 is normal, a smaller
number yields more bounce, larger is more rigid.

Left Button

Computes an axis aligned bounding box around the selected prims and fills in the Radius, Width and Mass
settings for the left wheel on the specified axle. The dimensions and mass can be adjusted after the scan is complete.

Right Button

Computes an axis aligned bounding box around the selected prims and fills in the Radius, Width and Mass
settings for the right wheel on the specified axle. The dimensions and mass can be adjusted after the scan is complete.

Tire Type

The type of tire to use on the vehicle, which principally sets the tire friction.

Default Radius

The vertical size of the tire from its center to an edge in world units

Default Width

The lateral size of the tire from edge to edge in world units

Default Mass

The mass of the wheel, tire and all suspension components, below the suspension spring, in kg

# Left

The Radius and Width, in world units, and the Mass, in kg, of scanned wheels on the left side of the
specified axle. Unscanned wheels will use the Default settings.

# Right

The Radius and Width, in world units, and the Mass, in kg, of scanned wheels on the right side of the
specified axle. Unscanned wheels will use the Default settings.

Back Button

Return to the Basic page

Create Button

Create a vehicle simulation using the current settings

Next Button

Go to the Next Steps page.

Reset Button

Reset the Axles page properties to their default values

Next Steps Page

VehicleNextStepsPage

Once the Vehicle Wizard has create all of the needed prims to run a vehicle simulation, there is still more work to do. The rendered mesh must be animated by linking it to the Vehicle Wizard, a ground surface to drive on is needed and the physics settings of the vehicle can be tuned. The Next Steps page will be updated and provides additional detail.

Property

Description

Back Button

Return to the Axles page

Create Button

Create a vehicle simulation using the current settings

Vehicle Wizard Collision Groups

The Vehicle Wizard does not create a drivable surface, but it does create collision groups to prevent the wheels of the car from colliding with the chassis, for example. One of the collision groups created is called GroundSurfaceCollisionGroup, which is set up to prevent collisions with objects in the VehicleWheelCollisionGroup. This prevents the wheels from colliding with the ground surface (instead, tire collisions with the surface are detected using ray casts). If Collision Geometry is enabled, be sure the driving surface is a member of the GroundSurfaceCollisionGroup.

To add a simple, drivable surface for testing, select Physics > Add > Ground Plane. If the Collision Geometry was enabled, the surface’s CollisionGroup must be set. On the stage, find the staticPlaneActor’s collisionPlane and select it. In the Details panel, find the Bind CollisionGroup drop down and select the GroundSurfaceCollisionGroup. When using custom drivable surfaces, ensure they are all members of the GroundSurfaceCollisionGroup by also setting the CollisionGroup of their collision objects to GroundSurfaceCollisionGroup.

VehicleCollisionGroup

Animating the Vehicle’s Rendered Mesh

Once the physics representation of the vehicle has been created, the vehicle’s rendered mesh can be linked to it. Select the Chassis root primitive, created as described in the Authoring the Vehicle’s Rendered Mesh section, above, and child it to the /WizardVehicle/Vehicle primitive, if the vehicle was created with the Vehicle Wizard, or the /Vehicle primitive if a Vehicle Sample was loaded. The Chassis transform may need to be moved so the rendered vehicle lines up with the physics box as much as possible. The rendered vehicle mesh should now move around with the vehicle.

The Vehicle Wizard creates a box to visualize the chassis when no other mesh is connected to the vehicle. It can be removed by selecting the /WizardVehicle/Vehicle/ChassisRender primitive on the stage and deleting it or hiding it, by clicking on the eye icon, next to it.

Aligning the Tires with the Vehicle

At this point, the physics representation of the tires will not align properly with the rendered, mesh representation. Move the physics representation of the tires by selecting each of them in the Viewport window and then dragging them into position.

For improved accuracy, the X, Y and Z position of each wheel in the rendered mesh hierarchy can be copied into the physics Position transforms. The Vehicle Wizard primitives that need updating are named, “/WizardVehicle0/Vehicle/LeftWheel0”, “/WizardVehicle0/Vehicle/RightWheel0”, “/WizardVehicle0/Vehicle/LeftWheel1” and “/WizardVehicle0/Vehicle/RightWheel1”. The Vehicle Sample wheels are named “FrontLeftWheel”, “FrontRightWheel”, “RearLeftWheel” and “RearRightWheel”.

Adjusting the Tire Radii

Some vehicles have different tire radii for the front and rear tires. Since the Vehicle Wizard only accepts a single tire radius for all tires, the tire radii that are different must be manually adjusted. Find the wheel components created by the wizard and adjust their tire radii. The wheel components are called “/WizardVehicle0/Wheel0” and “/WizardVehicle0/Wheel1”. Each have a radius edit box that changed.

The vehicle wheels also have a render and collision representation whose radii should be modified, too. Click the “/WizardVehicle0/Vehicle/LeftWheel0/Render” primitive (or the appropriate primitive for the tire that must be changed), select the Details panel and scroll to the bottom to find the radius.

Likewise, to update the collision tire radius, find the “/WizardVehicle0/Vehicle/LeftWheel0/Collision” primitive (or the appropriate primitive for the tire that must be changed), select the Details panel and scroll to the bottom to find the radius.

VehicleTireRadius

Authoring Tool

Whenever the physics tires are moved or re-sized, however, there are physics properties that must be updated. A tool has been provided to simplify this process. First select the Vehicle primitive, click on the PhysX Vehicle Properties tab (which may have to be opened under the Physics > PhysX Vehicle Properties menu) and then click on the Authoring panel’s Apply button. The physics properties that are updated by the Authoring tool include the point at which the suspension, tire and wheel forces are applied.

VehicleAuthoring

Once the tires align with the physics representation, child all the non-rotating parts to their respective “Wheel” transforms and all of the rotating parts to their respective “Tire” transforms. The transforms themselves will have to be animated through a script, which will be described in the next section.

If the tire render primitives are no longer needed, they can be deleted or hidden.

Animating the Wheels

If it is satisfactory to allow the physics to animate the wheels and tires, all of the rotating wheel and tire parts of the rendered mesh can simply by linked to the “/Vehicle/FrontLeftWheel”, “/Vehicle/FronRightWheel”, “/Vehicle/RearLeftWheel”, “/Vehicle/RearRightWheel” primitives.

However, if it is preferred to have non-rotating wheel parts that steer and compress, but not rotate with the tires, then a more sophisticated approach is required and the more complicated hierarchy described in Authoring the Vehicle’s Rendered Mesh and animated in Copying Transforms is required.

Copying Transforms

The position and orientation of the physics representation of the wheels must be broken apart into three components and copied into the rendered mesh representation after each simulation step, or update.

This can only be accomplished using a Python script. The exact math to do this is different for every vehicle and suspension configuration, but the two very common configurations are provided as an example in the following script for a double wishbone and a swing arm configuration. The front tires use a double wishbone and simply move up and down to compress the tire. The rear tires use a swing arm configuration. The angle of the swingarm is calculated from the compression of the tires and the swing arm radius. This code is used to load a USD file, register for an update callback, and then animate the suspension.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
 import math

 import omni.Create.editor
 import omni.usd

 from pxr import Usd, UsdGeom, Sdf, Gf, PhysxSchema, PhysicsSchema


 # Put the name of your USD file here.
 myStageName = "C:/Users/Downloads/myAnimatedVehicle.usd"

 myVehiclePrimName = "/World/WizardVehicle0/Vehicle"

 myFrontLeftName = "/LeftWheel0"
 myFrontRightName = "/RightWheel0"
 myRearLeftName = "/LeftWheel1"
 myRearRightName = "/RightWheel1"

 frontLeftTirePath = myVehiclePrimName + myFrontLeftName
 frontRightTirePath = myVehiclePrimName + myFrontRightName
 rearLeftTirePath = myVehiclePrimName + myRearLeftName
 rearRightTirePath = myVehiclePrimName + myRearRightName

 myFrontLeftSuspensionName = "/FrontLeftSuspension"
 myFrontRightSuspensionName = "/FrontRightSuspension"
 myRearLeftSuspensionName = "/RearLeftSuspension"
 myRearRightSuspensionName = "/RearRightSuspension"

 frontLeftSuspensionPath = myVehiclePrimName + myFrontLeftSuspensionName
 frontRightSuspensionPath = myVehiclePrimName + myFrontRightSuspensionName
 rearLeftSuspensionPath = myVehiclePrimName + myRearLeftSuspensionName
 rearRightSuspensionPath = myVehiclePrimName + myRearRightSuspensionName

 myFrontLeftWheelName = "/FrontLeftWheel"
 myFrontRightWheelName = "/FrontRightWheel"
 myRearLeftWheelName = "/RearLeftWheel"
 myRearRightWheelName = "/RearRightWheel"

 frontLeftWheelPath = frontLeftSuspensionPath + myFrontLeftWheelName
 frontRightWheelPath = frontRightSuspensionPath + myFrontRightWheelName
 rearLeftWheelPath = rearLeftSuspensionPath + myRearLeftWheelName
 rearRightWheelPath = rearRightSuspensionPath + myRearRightWheelName


 class AnimatedVehicleClass:

     def load_animation(self):
         # Get all of the necessary prims
         self._vehiclePrim = self._stage.GetPrimAtPath(myVehiclePrimName)

         self._frontLeftTire = self._stage.GetPrimAtPath(frontLeftTirePath)
         self._frontLeftSuspension = self._stage.GetPrimAtPath(frontLeftSuspensionPath)
         self._frontLeftWheel = self._stage.GetPrimAtPath(frontLeftWheelPath)

         self._frontLeftSuspension.CreateAttribute("xformOpOrder", Sdf.ValueTypeNames.String, False).Set(["xformOp:translate", "xformOp:orient", "xformOp:scale"])
         self._frontLeftWheel.CreateAttribute("xformOpOrder", Sdf.ValueTypeNames.String, False).Set(["xformOp:translate", "xformOp:orient", "xformOp:scale"])
         self._frontLeftSuspension.CreateAttribute("xformOp:orient", Sdf.ValueTypeNames.Quatf, False)
         self._frontLeftWheel.CreateAttribute("xformOp:orient", Sdf.ValueTypeNames.Quatf, False)

         self._frontRightTire = self._stage.GetPrimAtPath(frontRightTirePath)
         self._frontRightSuspension = self._stage.GetPrimAtPath(frontRightSuspensionPath)
         self._frontRightWheel = self._stage.GetPrimAtPath(frontRightWheelPath)

         self._frontRightSuspension.CreateAttribute("xformOpOrder", Sdf.ValueTypeNames.String, False).Set(["xformOp:translate", "xformOp:orient", "xformOp:scale"])
         self._frontRightWheel.CreateAttribute("xformOpOrder", Sdf.ValueTypeNames.String, False).Set(["xformOp:translate", "xformOp:orient", "xformOp:scale"])
         self._frontRightSuspension.CreateAttribute("xformOp:orient", Sdf.ValueTypeNames.Quatf, False)
         self._frontRightWheel.CreateAttribute("xformOp:orient", Sdf.ValueTypeNames.Quatf, False)

         self._rearLeftTire = self._stage.GetPrimAtPath(rearLeftTirePath)
         self._rearLeftSuspension = self._stage.GetPrimAtPath(rearLeftSuspensionPath)
         self._rearLeftWheel = self._stage.GetPrimAtPath(rearLeftWheelPath)

         self._rearLeftSuspension.CreateAttribute("xformOpOrder", Sdf.ValueTypeNames.String, False).Set(["xformOp:translate", "xformOp:orient", "xformOp:scale"])
         self._rearLeftWheel.CreateAttribute("xformOpOrder", Sdf.ValueTypeNames.String, False).Set(["xformOp:translate", "xformOp:orient", "xformOp:scale"])
         self._rearLeftSuspension.CreateAttribute("xformOp:orient", Sdf.ValueTypeNames.Quatf, False)
         self._rearLeftWheel.CreateAttribute("xformOp:orient", Sdf.ValueTypeNames.Quatf, False)

         self._rearRightTire = self._stage.GetPrimAtPath(rearRightTirePath)
         self._rearRightSuspension = self._stage.GetPrimAtPath(rearRightSuspensionPath)
         self._rearRightWheel = self._stage.GetPrimAtPath(rearRightWheelPath)

         self._rearRightSuspension.CreateAttribute("xformOpOrder", Sdf.ValueTypeNames.String, False).Set(["xformOp:translate", "xformOp:orient", "xformOp:scale"])
         self._rearRightWheel.CreateAttribute("xformOpOrder", Sdf.ValueTypeNames.String, False).Set(["xformOp:translate", "xformOp:orient", "xformOp:scale"])
         self._rearRightSuspension.CreateAttribute("xformOp:orient", Sdf.ValueTypeNames.Quatf, False)
         self._rearRightWheel.CreateAttribute("xformOp:orient", Sdf.ValueTypeNames.Quatf, False)

         rearRightWheelPosition = self._rearRightTire.GetAttribute("xformOp:translate").Get()
         self._rearWheelRestHeight = rearRightWheelPosition[2]
         self._swingArmRadius = rearRightWheelPosition.GetLength()

     def load_stage(self, a, b):
         if a == True:
             self._stage = self._usd_context.get_stage()
             self._physxVehicleInterface = omni.physxvehicle._physxVehicle.acquire_physx_vehicle_interface()

             self.load_animation()

     def __init__(self):
         self._opened = False

         print("Loading Stage " + myStageName)

         self._usd_context = omni.usd.get_context()

         self._physxVehicleInterface = None

         # Load the level
         self._usd_context.open_stage(myStageName, self.load_stage)

         # Subscribe to events
         self._editor = omni.Create.editor.get_editor_interface()
         self._editorUpdate = self._editor.subscribe_to_update_events(self.update)

         self._stageEventSubscription = self._usd_context.get_stage_event_stream().create_subscription_to_pop(self.on_stage_event)

     def on_stage_event(self, event):
         if (event.type == int(omni.usd.StageEventType.CLOSING)):
             self.shutdown()

     def shutdown(self):
         if self._opened:
             self._editor = None
             self._editorUpdate = None
             self._stageEventSubscription = None

     def animate(self):

         # Front Left
         wheelQueryResults = self._physxVehicleInterface.get_wheel_query_results(frontLeftTirePath)
         position = wheelQueryResults["localPosePosition"]
         rotation = wheelQueryResults["localPoseQuaternion"]
         frontLeftPosition = Gf.Vec3f(position[0], position[1], position[2])
         frontLeftRotation = Gf.Quatf(rotation[3], rotation[0], rotation[1], rotation[2])

         self._frontLeftSuspension.GetAttribute("xformOp:translate").Set(frontLeftPosition)

         frontLeftSuspensionRotation = Gf.Quatf(rotation[3], 0.0, 0.0, rotation[2])
         frontLeftSuspensionRotation.Normalize()
         self._frontLeftSuspension.GetAttribute("xformOp:orient").Set(frontLeftSuspensionRotation)

         frontLeftWheelRotation = Gf.Quatf(rotation[3], 0.0, rotation[1], 0.0)
         frontLeftWheelRotation.Normalize()
         self._frontLeftWheel.GetAttribute("xformOp:orient").Set(frontLeftWheelRotation)

         # Front Right
         wheelQueryResults = self._physxVehicleInterface.get_wheel_query_results(frontRightTirePath)
         position = wheelQueryResults["localPosePosition"]
         rotation = wheelQueryResults["localPoseQuaternion"]
         frontRightPosition = Gf.Vec3f(position[0], position[1], position[2])
         frontRightRotation = Gf.Quatf(rotation[3], rotation[0], rotation[1], rotation[2])

         self._frontRightSuspension.GetAttribute("xformOp:translate").Set(frontRightPosition)

         frontRightSuspensionRotation = Gf.Quatf(rotation[3], 0.0, 0.0, rotation[2])
         frontRightSuspensionRotation.Normalize()
         self._frontRightSuspension.GetAttribute("xformOp:orient").Set(frontRightSuspensionRotation)

         frontRightWheelRotation = Gf.Quatf(rotation[3], 0.0, rotation[1], 0.0)
         frontRightWheelRotation.Normalize()
         self._frontRightWheel.GetAttribute("xformOp:orient").Set(frontRightWheelRotation)

         # Rear Left
         wheelQueryResults = self._physxVehicleInterface.get_wheel_query_results(rearLeftTirePath)
         position = wheelQueryResults["localPosePosition"]
         rotation = wheelQueryResults["localPoseQuaternion"]

         angle = (position[2] - self._rearWheelRestHeight) / self._swingArmRadius
         rearLeftSuspensionRotation = Gf.Quatf(math.cos(0.5 * angle), 0.0, math.sin(0.5 * angle), 0.0)
         self._rearLeftSuspension.GetAttribute("xformOp:orient").Set(rearLeftSuspensionRotation)

         rearLeftWheelRotation = Gf.Quatf(rotation[3], 0.0, rotation[1], 0.0)
         rearLeftWheelRotation.Normalize()
         self._rearLeftWheel.GetAttribute("xformOp:orient").Set(rearLeftWheelRotation)

         # Rear Right
         wheelQueryResults = self._physxVehicleInterface.get_wheel_query_results(rearRightTirePath)
         position = wheelQueryResults["localPosePosition"]
         rotation = wheelQueryResults["localPoseQuaternion"]

         angle = (position[2] - self._rearWheelRestHeight) / self._swingArmRadius
         rearRightSuspensionRotation = Gf.Quatf(math.cos(0.5 * angle), 0.0, math.sin(0.5 * angle), 0.0)
         self._rearRightSuspension.GetAttribute("xformOp:orient").Set(rearRightSuspensionRotation)

         rearRightWheelRotation = Gf.Quatf(rotation[3], 0.0, rotation[1], 0.0)
         rearRightWheelRotation.Normalize()
         self._rearRightWheel.GetAttribute("xformOp:orient").Set(rearRightWheelRotation)

     def update(self, deltaTime):
         if self._editor.is_playing():
             self._opened = True
             self.animate()

 animatedVehicle = AnimatedVehicleClass()

Driving the Vehicle

After the Vehicle Wizard has created the vehicle, try driving it around a bit to see how it behaves. The vehicle can be controlled using the keyboard or a connected gamepad.

Every vehicle has some additional properties to control it. On the stage, find and select the vehicle to adjust. Then select the Physics > PhysX Vehicle Properties menu item. A window with Vehicle Controller and Camera Controller panels will appear. To select which vehicle to control using the input system, check or un-check the Input Enabled check box. To enable the mouse, check the Mouse Enabled check box. If it is undesirable to automatically go into reverse when the brake is held while at rest, un-check the Auto Reverse Enabled checkbox.

VehiclePhysXProperties

Vehicle Cameras

Driving a vehicle around the Create Viewport can be difficult because the vehicle will quickly drive out of frame. A couple of simple camera controllers were created to help with this problem. To add one, select the vehicle to follow, click on the PhysX Vehicle Properties window and click the Add Follow Camera or Add Drone Camera buttons. The Follow Camera creates a camera that simulates following the vehicle from a chase vehicle and the Drone Camera simulates following the vehicle from the air, in a drone. Multiple cameras can be created for each vehicle and their settings can be tuned for different behaviors.

VehicleAddCameras

To select the camera from which to follow the vehicle, click on the camera button in the top left corner of the Viewport window, then click on the Camera in the pop up menu and select the vehicle’s follow or drone camera. The camera position is not updated until the simulation is started by pressing the Play button, so the initial view may be black, but press Play, and the camera will move into position.

VehicleSelectCamera