.. include:: definitions.rstinc ============================================= 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 `_. .. _agxviewer_ref: --------- 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 :numref:`table-agxviewer-commandline-arguments` Arguments to agxViewer. Sample use of agxViewer: .. code-block:: console 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 :numref:`table-agxviewer-keybindings`: Keyboard bindings. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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. Possible EGL troubleshooting in Linux ------------------------------------- #. Make sure your distribution has glvnd support. #. Test that system provided utils can use EGL, e.g. ``eglinfo``. #. 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. #. Make sure Linux kernel graphics driver and corresponding vendor OpenGL libraries have matching version number. ^^^^^^^^^^^^ ImageCapture ^^^^^^^^^^^^ The agxViewer example above demonstrates how to capture images to file. The class used for this is ``agxOSG::ImageCapture``. .. code-block:: c++ 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. ^^^^^^^^^^^^ 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 `` - Decides the number of frames that should be captured per second. • ``--videoFPS `` - Decides the FPS of the created video. • ``--videoName `` - 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 `` is used. Video capture can also be started using the API: .. code-block:: c++ 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 .. code-block:: c++ vc->stopCapture(); // Pause // Do something vc->startCapture(); // Resume The video capture process (FFMPEG) can be stopped, allowing a new video file to be created: .. code-block:: c++ 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: .. code-block:: c++ 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. .. _key-bindings: ^^^^^^^^^^^^ Key bindings ^^^^^^^^^^^^ .. _table-agxviewer-keybindings: .. csv-table:: Keyboard bindings :header: "Key", "Description" :widths: auto "**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" ^^^^^^^^^ Arguments ^^^^^^^^^ .. _table-agxviewer-commandline-arguments: .. csv-table:: Arguments to agxViewer :header: "Argument", "Explanation" :widths: auto "``--agxOnly (shorthand: -a)``", "Only step AGX, no graphics" "``--allowExternal``", "Enable external remote command connections" "``--attachScript ``", "Specified a Python file that should be executed after a scene is loaded. Can be specified multiple times for multiple scripts" "``--broadPhase ``", "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 where captured frames are stored" "``--captureFPS ``", "Specify the desired capture rate for image capture" "``--captureFiletype ``", "File type of captured frames, eg \'png\' (default is \'bmp\')" "``--captureVideo <1 | 0>``", "Enable | disable ffmpeg capture of video to disk" "``--cfg ``", "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 ``", "File name for co simulation input data" "``--coSimulationOutputFile ``", "File name for co simulation output data" "``--coSimulationServer``", "Start as a controllable co-simulation server" "``--connect (: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 ``", "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 ``", "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 ``", "The journal format" "``--journalFrequency ``", "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 ``", "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