37. 3D Viewer and default rendering

The tutorials and also the application agxViewer are all based on the class agxOSG::ExampleApplication. It is a class that is responsible for parsing command line arguments, reading files, creating a 3D window, stepping simulation and rendering the simulation. The 3D rendering is based on OpenSceneGraph.

37.1. agxViewer

agxViewer is an application for reading various files (.agx, .aagx, .agxScene, …). It is the default program for opening: .agx, .aagx, .agxPy, and agxPyz … files.

If you want to use agxViewer (and any other example/tutorial) from the command line/terminal, make sure you execute the setup_env.bat file in the installed agx directory from the cmd/terminal-instance. Otherwise it will not be able to find all the required dll-files and configuration files.

Help can be obtained with the argument:

cmd> agxViewer –help

For a list of available arguments, see Table 37.2 Arguments to agxViewer.

Sample use of agxViewer:

agxViewer --sceneFile template_scene1.agxScene --startPaused --stopAfter 3.1 --capture 1 --captureFPS 30 --saveScene store.agx --saveAfter 3

The above example will:

  • Load the scene file template_scene1.agxScene

  • Start paused (press ‘e’ to continue)

  • Exit the application after 3.1 seconds of simulation time

  • Enable the capture of each frame as a .bmp file (agx__0001.bmp…)

  • Capture 30 images/second (in simulation time to achieve real-time)

  • 3.0 seconds into the simulation, the scene will be stored to disk with the name ‘store.agx

For a list of available key bindings of the agxViewer application, see Table 37.1: Keyboard bindings.

37.1.1. 3D Rendering in Linux

To create an OpenGL context in Linux, GLX functions has traditionally been used to communicate with a X-server and create the context. This is also what OpenSceneGraph does when built to use OpenGL. To perform headless rendering, possible in the cloud or on a cluster, the requirement of having a X-server present to be able to use GLX can be unwanted.

It does not matter if it is a virtual framebuffer X-server that will not provide hardware acceleration or a real X-server configured to use one or more system GPUs and allow for not having a physical display connected. Neither of these two options is ideal for headless rendering.

Modern Linux distributions which have OpenGL libraries that support Vendor-Neutral-Dispatch (glvnd) usually also support EGL. With EGL it is possible to create an OpenGL Context without the requirement for having a X-server running. In such a setup, all of the libraries libGL, libEGL, libGLX, libOpenGL links to libGLdispatch which handles that there can be multiple drivers and maps API calls to the right driver instead of early days of OpenGL on Linux where drivers fought over which one should provide libGL.

EGL is supported in AGX packades for Ubuntu-18.04 and newer and CentOS 7.4 and newer where the base distribution have the required libraries and they are built in the right way.

To make use of headless rendering, the --osgWindow 0 flag can be used and seamlessly agxOSG::ExampleApplication will use EGL in Linux to create a graphics context and provide OpenSceneGraph with said context. If EGL is not configured correctly on the machine or the EGL context creation does not succeed, OpenSceneGraph will try to create a context instead via GLX as fallback.

37.1.1.1. Possible EGL troubleshooting in Linux

  1. Make sure your distribution has glvnd support.

  2. Test that system provided utils can use EGL, e.g. eglinfo.

  3. Check that EGL Installable Client Driver (ICD) files are placed correctly, normally in /usr/share/glvnd/egl_vendor.d and that the correct vendor EGL libraries are referenced. Normally done automatically but can be needed when using Docker.

  4. Make sure Linux kernel graphics driver and corresponding vendor OpenGL libraries have matching version number.

37.1.2. ImageCapture

The agxViewer example above demonstrates how to capture images to file. The class used for this is agxOSG::ImageCapture.

agxOSG::ImageCapture* myCapture = application->getImageCapture();

ImageCapture has methods for

  • changing the file format (setPostfix)

  • changing the image logging frequency(setFps)

  • turning logging on or off

  • changing the image destination(setDirectoryPath)

The last one is important if the executable (agxViewer, your tutorial, …) is stored in a folder where the default user lacks writing access – in this case, logging the images would fail and a different location for the images should be given.

37.1.3. VideoCapture

ExampleApplication can capture video from the simulation using FFMPEG if a graphics window is present. To start video capturing from the agxViewer command line, the following, arguments can be used:

  • --captureVideo 1 - Starts the video capture when the simulation starts.

  • --captureFPS <float> - Decides the number of frames that should be captured per second.

  • --videoFPS <float> - Decides the FPS of the created video.

  • --videoName <str> - Name of file, or path and name of capture video file.

The video will be saved as agx_mov.mp4 in the working directory unless --videoName <str> is used.

Video capture can also be started using the API:

app->setupVideoCaptureRenderTotexture();
app->setAllowWindowResizing(False);
auto* vc = app.getVideoServerCapture();
vc->getEnableSyncWithSimulation();  // Synchronize the capture with the simulation time
vc->startCapture();

where app is an instance of the agxOSG::ExampleApplication. The video capture can be paused and resumed using

vc->stopCapture();  // Pause
// Do something
vc->startCapture();  // Resume

The video capture process (FFMPEG) can be stopped, allowing a new video file to be created:

vc->stopProcess();
vc->setFilename("video_file_2");  // Change the file name to avoid overwriting the previous file
vc->startProcess();  // Start recording a new video

The capture and video FPS can be changed as well:

vc->setImageCaptureFPS(60);
vc->setVideoFPS(20);

The capture FPS specifies the number of frames that will be captured each second, and the video FPS decides the playback speed of the video. A real time factor can be calculated by dividing the capture FPS with the video FPS, where a number less than 1 yields a slow motion video, and a number greater than 1 produces a timelapse.

See the AGX Dynamics API Documentation for the agxOSG::VideoFFMPEGPipeCapture class for more information on configuring the video capture.

37.1.4. Key bindings

Table 37.1 Keyboard bindings

Key

Description

Numeric keys, function keys

Select scene

a

not used (reserved for use in specific scenes)

b

Toggle statistics reporting to screen (debug rendering)

c

contact reduction (trimesh) circles between binning3, off, binning2

d

contact reduction circles between off, binning2, binning3

e

Toggle simulation run/pause

f

Toggle full screen

g

Toggle debug rendering

h

move camera to the left

i + left mouse

information about selected body

j

move camera backwards

k

move camera to the right

l

move camera downwards

m + left mouse

camera follows selected body

m

reserved for memory debugging

n

Toggle statistics reporting to screen (debug rendering) and console

o

move camera upwards

p

Toggle merge/split functionality

q

Toggle real time synchronization for image capture

r

In paused simulation, take a single time step

s

Toggle OSG statistics

t

Toggle synchronization of image capture with wall/simulation time

u

Move camera upwards

v

gravity points towards screen down

w

circle between osg shading modes (polygon, wire frame, points)

x + left mouse

remove selected body

left alt + x

move all non-static rigid bodies to the left

y

Toggle update debug render cache for simulation in pause mode

z

not used (reserved for use in specific scenes)

A

Toggle debug rendering of AABB trees

B

Toggle debug rendering of bounding volumes (spheres or boxes depending on broad phase algorithm)

C

Print camera data to console

D

Delete all objects from simulation

E

Circle through solvers

F

Toggle text debug rendering

G

Toggle OSG rendering

H

Print help screen to console

I

restore simulation from scene.agx

J

Update collision detection

K

Toggle debug coloring mode

L

Toggle osg lightning

M

reserved for memory debugger

N

Reload scene

O

save simulation to scene.agx

P

run parallel performance test

Q

Toggle wait in calling update (real-time sync)

R

Re-read specified configuration file

S

Toggle osg on screen stats

T

Toggle enable scene decorator

U

dump screenshot for povray

V

gravity points in original direction

W

save simulation to saved_scene.scene

X

Toggle simulation dump

left alt + X

move all non-static rigid bodies to the right

Y

Toggle auto sleep of resting objects

Z

Dump scene to osg-file

+

Select next scene

Select previous scene

return

Shoot sphere in camera direction

drag left mouse

rotate camera

mouse wheel up/down

adjust camera movement speed

left ctrl + drag left mouse

add temporary ball joint to selected body

left ctrl + drag mid mouse

add temporary lock joint to selected body

left ctrl + drag right mouse

add temporary lock joint resetting rotation to selected body

left alt + drag left mouse

move selected body/geometry (no dynamics)

left alt + drag right mouse

rotate selected body/geometry (no dynamics)

space

Reset camera to view all objects

esc

Quit

Left

Turn batch debug rendering off

Right

Turn batch debug rendering on

Up

Increase debug rendering scale

Down

Decrease debug rendering scale

.

Toggle shader state

F10

Toggle video capture on/off

F12

Toggle image capture on/off

37.1.5. Arguments

Table 37.2 Arguments to agxViewer

Argument

Explanation

--agxOnly  (shorthand: -a)

Only step AGX, no graphics

--allowExternal

Enable external remote command connections

--attachScript <filename>

Specified a Python file that should be executed after a scene is loaded. Can be specified multiple times for multiple scripts

--broadPhase <grid | sweepAndPrune>

Specifies the broad phase algorithm. Default is sweep and prune

--calculateResiduals

Switch on calculation of residuals during solver iterations

--capture <1 | 0>

Enable | disable capturing of screens to disk

--captureDirectory <directory>

Directory where captured frames are stored

--captureFPS <float>

Specify the desired capture rate for image capture

--captureFiletype <fileType>

File type of captured frames, eg 'png' (default is 'bmp')

--captureVideo <1 | 0>

Enable | disable ffmpeg capture of video to disk

--cfg <cfg-file>

Read in a configuration file

--clearColor r g b

Specifies the clear color for OpenGL

--clientQueue <1..n>

Specifies the maximum queue of simulation frames that the remote client will queue up before purging the queue. Default is 1

--coSimulationInputFile <filename>

File name for co simulation input data

--coSimulationOutputFile <filename>

File name for co simulation output data

--coSimulationServer

Start as a controllable co-simulation server

--connect  <hostname>(:port)

Connect to a remote server

--contactReducer <0,1,2,3>

Specify the default contact reduction bin size between bodies, 0-disabled, 1-3 binResolution

--cycleThroughScenes

Opens the next scene once the old one has been closed

--disableArchiveDate

Do not log current execution date output archive, but rather AGX build date. Mostly for unittests

--disableUuid

Do not generate unique uuid for each new Serializable object. Mostly for unittests

--dumpEnable

Enable dumping of simulation to disk

--dumpInterval

Specify the interval (in seconds) between each dump of simulation to disk

--forceSilent

Force redirect stdout | stderr to null device

--granularContactMode <2 | 3 | 4>

different granular contact modes (for internal usage).

--gravity x y z

Specify the gravity vector

--gravityEnabled <1 | 0>

0 will disable gravity, 1 will enable it (default)

--groundPlane <heightOverZero>

Create a plane with default material at specified height in Z

--help (shorthand: -h)

Prints help screen with command line arguments; exits

--interactiveRemoteClient

Use when interactiveRemoteClient will connect to AGX

--journal32bit

Force 32bit floating point data in journal

--journalConfiguration <filename>

When recording a journal session, this is the file listing the buffers and values to record

--journalDisableSceneLoading

Load the journal without initializing the simulation

--journalFormat <HDF5|CUSTOM>

The journal format

--journalFrequency <frequency>

The frequency of journal frames

--journalAppend

Appends a session previously recorded journal if an .agxJournal file is specified as an argument. See –sessionName

--journalIncrementalStructure

Enables incremental journal recording. Important when simulation structure is changed during journal recording

--journalPlayback <filename>

Initiates playback from a previously recorded journal. See –sessionName

--journalPlaybackEofMode < LOOP | PAUSE | SIMULATE | RECORD >

What do do when journal EOF is reached. LOOP: Loop from start point, PAUSE: Pause playback, SIMULATE: Switch to simulation from current state, RECORD: Same as SIMULATE but also record new simulation frames to current journal session

--journalPlaybackStartAt <time | END>

Where to start journal playback

--journalPlaybackStopAt <time | END>

Where to stop journal playback

--journalRecord

Initiates recording to a journal. See –sessionName and –journalRecordPath

--journalRecordPath <filename>

When recording a journal session, this is the journal in which the session will be stored

--journalRecordStartAt <time>

When recording a journal session, this is the time when the recording will start

--journalStep <timeStep>

Inverse frequency of journal frames

--listSessions <filename>

List the sessions stored in the given journal

--mcp <BLOCK | KELLER | HYBRID>

Specify which MCP algorithm to use

--multiSamples <0..n>

Number of multi samples for anti aliasing (0 for off; default: 4)

--numImpactIterations <1..n>

Number of iterations during impact stage 1

--numIterations <1..n>

Number of iterations during normal solve (i.e., no impacts) This will override file any previous read value specified by file or script

--numIterationsForIterateLast <1..n>

Number of iterations performed on special constraints,

--numLCPIterations <1..n>

Max number of iterations for LCP solver

--numPPGSIterations <1..n>

Number of iterations during the Parallel-Projected-Gauss-Seidel solve, if enabled This will override file any previous read value specified by file or script

--numPostImpactIterations <1..n>

Number of iterations during impact stage 2 (can be less than for impact stage 1)

--numThreads <n>

Specify number of threads available for AGX

--osgWindow <1 | 0>

Render graphics, but optionally hidden window, useful for offline render to texture targets

--particleRenderMode <0 | 1 | 2>

set particle render mode < SPRITES(0) | QUAD_SPRITES(1) | TRIANGLES(2) >

--pauseAfter <float>

Will pause running simulation after this time stamp

--portFile <filename>

Print open ports to a file

--preIntegratePositions <1 | 0>

0 will integrate positions at end of timestep, 1 will integrate at beginning of timestep.

--profileFrequency <Hz>

Frequency of profiling, both thread timeline and task timings

--quickProfiling

Does a quick profiling (to analyze performance questions)

--quickProfilingFile <filename>

Send quick profiling output to this file instead of standard output

--quickProfilingNumTasks <integer>

The number of tasks to include in the quick profiling

--rcsPort <n>

Choose port for remote command server, default 5656, 0 will automatically find an available port

--rcs

Start remote command server (default port 5656, modify with –rcsPort)

--realTime <1 | 0>

Sync stepping simulation to real clock time (1) or run as fast as possible (0). Default: 1

--renderDebug <1 | 0>

Specify whether rendering using agx Debug renderer is enabled or not

--renderGrid

Turns rendering of (hierarchical) grid cells on

--renderOsg <1 | 0>

Specify whether rendering using OSG primitives is enabled or not

--renderProxyShadows <1 | 0>

If 1 geometries rendered by RenderProxys cast and recieves shadows. Default is 0

--resetTimersAtTime <time>

Reset task profiling accumulation timers at the given time

--save <filename>

Create scene and write to specified filename

--saveAfter <X seconds>

Step forward system until we read X seconds in simulation time then the content of the scene will be stored to disk

--saveScene <filename>

When save scene button is pressed, this is the file where the scene will be stored

--scene <n>

In a simulation with several scenes, load the n-th one (1…n)

--sceneFile <path>

Path to a .scene file that will be read

--server

Start a remote debugger server

--serverCompress <0 | 1>

Specify whether compression of data for server will be used or not

--serverPort  <port>

Specify a socket port which will be used for listening for connection from a remote client

--serverTimeStep  <timeStep>

Specify the rate by which data is sent to the remote listener. Should be a multiple of the simulation time step

--serverWait <0 | 1>

Specify whether the server should wait for the client to ask for more data before sending a frame

--sessionName

When recording or playing a journal, this is the session that will be written to or read from

--shadowMethod <0,1,2>

Select shadow method

--solver <MULTI | ITERATIVE>

Specify which solver to use

--startPaused   (shorthand: -p)

Start the simulation in paused mode

--stopAfter <X seconds> (shorthand: -s <X>)

Step forward system X seconds in simulation time, relative to the initial simulation time

--stopAfterFrame <X steps>

Step forward system until we reach X simulation steps

--stopAt <X seconds>

Step forward system until we read X seconds in simulation time

--synchronize <1 | 0>

Synchronize image capture with Simulation time

--targetFPS <float>

Specify number of graphic window updates per second. Defaults to timesteps/second.

--taskProfile

Enable export of task timing data

--threadTimeline <format>

Enable thread timeline profile. Format can be either ‘svg’ or ‘chrome’

--timeStep <float>

Specify the time step (dt) used for stepping the simulation

--translate x y z

Translate the debug rendering of the scene

--twoStagesImpacts <1 | 0>

Enable two stages impact (might be slow) default: 0

--unittest  (shorthand: -u)

Run all unit tests in file

--unittestPassOnExceptions

Unit tests will not catch exceptions, but pass them on

--use32bitGranularBodySolver <0 | 1>

Specify if the Real32 granular body solver should be used

--useContactWarmstarting <0 | 1>

Toggles if warmstarting should be used for contacts with direction friction. Default 0

--useGranularWarmStarting <0 | 1>

Specify if warm starting for the granular GS solvers should be used

--useIndexSetWarmStarting <0 | 1>

Toggles if indexset should be warmstarted. Default 1

--useParallelPGS <0 | 1>

Specify if the ParallelPGS solver should be used

--useShaders

Use the shader based render state

--useShadows

Enable shadowing

--vSync <1 | 0>

Enable | Disable vSync

--version (shorthand: -v)

Prints version number, exits

--videoFPS <float>

Specify the desired fps for videos created using ffmpeg

--videoName <str>

  • Name of file

or path and name of capture video file.

--window width height

Specifies the size of the rendering window in pixels

--windowTitle title

Specifies the title of the rendering window. Default title is ‘AGX Dynamics’

In order to get an overview over all command line arguments, use the –help switch: agxViewer --help

37.2. agxArchive

agxArchive is an utility that can be used to convert between .agx and .aagx file, investigate a serialization file and creating a script archive.

37.2.1. Command line arguments

Table 37.3 Arguments to agxArchive

Argument

Explanation

--help/-h

Show help

--disableUuid

Disable UUID generation for deterministic output

--generate/-g

Generate a random UUID string

--library <library name>

Pre-load an AGX Dynamics module library (.dll/.so) to enable deserialization of features not part of agxCore/agxPhysics

--pack/p

Create a compressed script archive

--unpack/-u

Decompress a script archive to disk

37.3. Usage

Investigate a serialization

The general use of agxArchive is to investigate a serialized file:

> agxArchive submarine.agx

Archive information
-------------------
Header               Algoryx:AgX Library 64Bit
AGX version          : 2.12.0.0-23170
Serialization version: 37
BuildDate            : Mar 30 2015
BuildTime            : 17:54:35
File format          : binary
File size            : 216601 bytes
Serialization date   :
Build flags
     USE_PARTICLE_SYSTEM=1
     USE_OSG=1
     USE_OPENCL=0
     SABRE_USE_SSE3=1
     UNITTEST_ENABLED=0
     SABRE_USE_PADDING=1
     USE_SSE=1
     USE_64BIT_ARCHITECTURE=1
     USE_REAL_FLOAT=0

37.3.1. Convert files

By supplying two files (.agx/.aagx) one can convert between these two file formats (ascii/binary) for serialization.

> agxArchive submarine.agx output.aagx
Reading input file: submarine.agx
Writing output file: output.aagx

37.3.2. Pack a script archive

If you have a Python script file together with some data, you can use agxArchive to pack these files into a compressed archive. Directories will recursively be compressed into the archive.

Usage: agxArchive <archive-name> files and directories

> agxarchive --pack submarine.agxPyz submarine.agxPy submarine.agx
submarine.agxPy
submarine.agx

Successfully archived 2 files to archive 'submarine.agxPyz'

37.3.3. Unpack a script archive

Usage: agxArchive <archive-name> <target directory>

> agxArchive --unpack submarine.agxPyz myScripts
Successfully decompressed archive 'submarine.agxPyz'' into directory 'myScripts'

37.3.4. Pre-loading a library

agxArchive is not linked against all AGX Dynamics runtime libraries. Therefore it can be necessary to explicitly load some libraries to enable de-serialization of specific features.

For example, objects in the namespace agxDrivetrain:: are part of the agxModel library. Reading an archive containing such objects will fail because the agxModel libary will not be loaded automatically. In some cases, the correct library can be derived from the namespace. For example, an object in the agxModel namespace will automatically be searched for in the agxModel dynamic library. To explicitly load a module, the –library argument can be used:

Usage: agxArchive <archive-name> –library name1 –library name2

> agxArchive myModel.agx --library agxModel --library agxTerrain

37.3.5. Increasing performance for high frequency simulations with graphics

By default the number of graphics window updates per second is set to 60 frames per second (fps) regardless of the simulation timestep. This will throttle graphic updates to 60 frames per second (fps), while the simulation still runs at full speed. When using high frequency simulations, ie > 500Hz (timestep < 0.002 seconds) this has a severe impact on the simulation performance. A target fps higher than 60 is unnecessary for most applications, but you can change it using --targetFPS <float>, or disable throttling altogether with --targetFPS 0

When stepping manually through a simulation, each simulation step will always update the graphics window.