How to run cgx in batch mode and create screenshots

Background

I have studied the documentation section B.14 about how to run cgx in batch mode. But I cannot figure out a problem.

I have this FBD file:

# Change file name to the job name you used.
read C:\Users\m3\AppData\Local\Temp\result-layer0-to-layer3.frd

capt "Layer 0 to 3"

# Data set number depends on how may things you saved!
ds 2 e 7

gonly off

rot y
frame
hcpy png right

gonly on

rot r 90
frame
hcpy png front

rot r 90
frame
hcpy png left

rot r 90
frame
hcpy png back

rot y
rot u 90
frame
hcpy png top

rot d 180
frame
hcpy png bottom

quit

Good case

When I run this FBD file like this, everything is fine:

cgx_STATIC.exe -b C:\Users\m3\AppData\Local\Temp\shot-710971079.fbd

The PNG files are stored next to CGX executable as expected:

2023-09-11 13_39_13-net48

And the CGX logs are:

on a Windows 10 machine, nodename ADMINISTRATOR, release 10, version 10.0  19041, machine 8664
 The win HOME was detected:C:\Users\m3
parameters:3 arguments:2
GL_MAX_EVAL_ORDER:32, mesh threads:1
 C:\Users\m3\AppData\Local\Temp\shot-710971079.fbd opened

 reading file
 # Change file name to the job name you used.
 file:C:\Users\m3\AppData\Local\Temp\result-layer0-to-layer3.frd opened
 reading frd format
 MODEL NAME:  record:    1UModel: 3D model Date: 2023-Sep-11 UTC
record:    1UUSER
record:    1UDATE              11.september.2023
record:    1UTIME              13:12:17
record:    1UHOST
record:    1UPGM               CalculiX
record:    1UVERSION           Version 2.20
record:    1UCOMPILETIME       Sat Apr  1 21:09:13     2023
record:    1UDIR
record:    1UDBN
record:    1UMAT    1RESIN
record:    2C                          2362                                     1
reading Nodes

 2362 nodes reallocated
record:    3C                          5651                                     1
reading Elements

 5651 elements reallocated
record:    1PSTEP                         1           1           1
record:  100CL  101 1.000000000        2362                     0    1           1
reading Dataset No:1
 gen lc[0] ncomps:4
ncomps:3 nvals:3
record:    1PSTEP                         2           1           1
record:  100CL  101 1.000000000        2362                     0    1           1
reading Dataset No:2
 gen lc[1] ncomps:6
ncomps:6 nvals:6
record:    1PSTEP                         3           1           1
record:  100CL  101 1.000000000        2362                     0    1           1
reading Dataset No:3
 gen lc[2] ncomps:1
ncomps:1 nvals:1
record: 9999
gtol calculated:8.495190e-05
 ready
 # Data set number depends on how may things you saved!

2 L  101 1.000000                      STRESS   Mises
 Extremal values from displayed mesh-entities:
 max:1.165530e-03 at node:1790
 min:0.000000e+00 at node:1

2 L  101 1.000000                      STRESS   Mises
 Extremal values from displayed mesh-entities:
 max:1.165530e-03 at node:1790
 min:0.000000e+00 at node:1

2 L  101 1.000000                      STRESS   Mises
 Extremal values from displayed mesh-entities:
 max:1.165530e-03 at node:1790
 min:0.000000e+00 at node:1

2 L  101 1.000000                      STRESS   Mises
 Extremal values from displayed mesh-entities:
 max:1.165530e-03 at node:1790
 min:0.000000e+00 at node:1
create right.png
 ready

2 L  101 1.000000                      STRESS   Mises
 Extremal values from displayed mesh-entities:
 max:1.165530e-03 at node:1790
 min:0.000000e+00 at node:1

2 L  101 1.000000                      STRESS   Mises
 Extremal values from displayed mesh-entities:
 max:1.165530e-03 at node:1790
 min:0.000000e+00 at node:1

2 L  101 1.000000                      STRESS   Mises
 Extremal values from displayed mesh-entities:
 max:1.165530e-03 at node:1790
 min:0.000000e+00 at node:1
create front.png
 ready

2 L  101 1.000000                      STRESS   Mises
 Extremal values from displayed mesh-entities:
 max:1.165530e-03 at node:1790
 min:0.000000e+00 at node:1

2 L  101 1.000000                      STRESS   Mises
 Extremal values from displayed mesh-entities:
 max:1.165530e-03 at node:1790
 min:0.000000e+00 at node:1
create left.png
 ready

2 L  101 1.000000                      STRESS   Mises
 Extremal values from displayed mesh-entities:
 max:1.165530e-03 at node:1790
 min:0.000000e+00 at node:1

2 L  101 1.000000                      STRESS   Mises
 Extremal values from displayed mesh-entities:
 max:1.165530e-03 at node:1790
 min:0.000000e+00 at node:1
create back.png
 ready

2 L  101 1.000000                      STRESS   Mises
 Extremal values from displayed mesh-entities:
 max:1.165530e-03 at node:1790
 min:0.000000e+00 at node:1

2 L  101 1.000000                      STRESS   Mises
 Extremal values from displayed mesh-entities:
 max:1.165530e-03 at node:1790
 min:0.000000e+00 at node:1

2 L  101 1.000000                      STRESS   Mises
 Extremal values from displayed mesh-entities:
 max:1.165530e-03 at node:1790
 min:0.000000e+00 at node:1
create top.png
 ready

2 L  101 1.000000                      STRESS   Mises
 Extremal values from displayed mesh-entities:
 max:1.165530e-03 at node:1790
 min:0.000000e+00 at node:1

2 L  101 1.000000                      STRESS   Mises
 Extremal values from displayed mesh-entities:
 max:1.165530e-03 at node:1790
 min:0.000000e+00 at node:1
create bottom.png
 ready

Bad case

But when running the CGX with the -bg parameter to run it in batch mode:

cgx_STATIC.exe -bg C:\Users\m3\AppData\Local\Temp\shot-710971079.fbd

No PNG image is created. The CGX logs are:

on a Windows 10 machine, nodename ADMINISTRATOR, release 10, version 10.0  19041, machine 8664
 The win HOME was detected:C:\Users\m3
parameters:3 arguments:2
 C:\Users\m3\AppData\Local\Temp\shot-710971079.fbd opened

 reading file
 # Change file name to the job name you used.
 file:C:\Users\m3\AppData\Local\Temp\result-layer0-to-layer3.frd opened
 reading frd format
 MODEL NAME:  record:    1UModel: 3D model Date: 2023-Sep-11 UTC
record:    1UUSER
record:    1UDATE              11.september.2023
record:    1UTIME              13:12:17
record:    1UHOST
record:    1UPGM               CalculiX
record:    1UVERSION           Version 2.20
record:    1UCOMPILETIME       Sat Apr  1 21:09:13     2023
record:    1UDIR
record:    1UDBN
record:    1UMAT    1RESIN
record:    2C                          2362                                     1
reading Nodes

 2362 nodes reallocated
record:    3C                          5651                                     1
reading Elements

 5651 elements reallocated
record:    1PSTEP                         1           1           1
record:  100CL  101 1.000000000        2362                     0    1           1
reading Dataset No:1
 gen lc[0] ncomps:4
ncomps:3 nvals:3
record:    1PSTEP                         2           1           1
record:  100CL  101 1.000000000        2362                     0    1           1
reading Dataset No:2
 gen lc[1] ncomps:6
ncomps:6 nvals:6
record:    1PSTEP                         3           1           1
record:  100CL  101 1.000000000        2362                     0    1           1
reading Dataset No:3
 gen lc[2] ncomps:1
ncomps:1 nvals:1
record: 9999
gtol calculated:8.495190e-05
 ready
 # Data set number depends on how may things you saved!

2 L  101 1.000000                      STRESS   Mises
 Extremal values from displayed mesh-entities:
 max:1.165530e-03 at node:1790
 min:0.000000e+00 at node:1

Question

I studied the documentation but I could not figure out why with -bg parameter, CGX wonā€™t create the PNG files.

I have to run CGX in batch mode since Iā€™m going to run it by another program to create the PNG files. I donā€™t want the user of the other program to observe the pop-up of the CGX graphic window.

Adding the command stack on to the FBD file didnā€™t help.

Iā€™m not sure if it is in the documentation, but it is tied to the way cgx works.

Basically (and Iā€™m skimping over a lot here) the 3D API that CalculiX GraphicX uses (OpenGL) renders the 3D scene to a ā€œframe bufferā€, a piece of memory to store a 2D pixel image.
The hcpy function basically copies the image from the frame buffer and saves it to a file.

If you use -bg there is no screen to render to, so no image.

Now, OpenGL does support off-screen rendering but itā€™s not automatic, the programmer has to explicitly program that to make it work. And if youā€™re rendering off-screen, how big should the image be?

1 Like

Right :white_check_mark:

Iā€™m reading the CGX version 2.21 source code. I see that HCPY calls createHardcopy() function that calls getTGAScreenShot() function that calls glutSetWindow() function and SaveTGAScreenShot() function that is calling glReadPixels() function like this:

/* This will save a screen shot to a file. */
void SaveTGAScreenShot(char *filename, int w, int h)
{
   char *imageData;
   imageData = (char *)malloc(sizeof(char) * w * h * 4);
   glReadPixels(0, 0, w, h,GL_RGBA,GL_UNSIGNED_BYTE, (GLvoid *)imageData);
   WriteTGA(filename,w,h,imageData);
   // release the memory
   free(imageData);
}

Iā€™m going to research further :books:

By the way, CGX source code sometimes considers the Windows OS by:

#ifdef WIN32
    sprintf (buffer, "move /y \"%s\" \"%s.fbb\"", datin, setname );
#else
    sprintf (buffer, "mv %s %s.fbb", datin, setname );
#endif

But there are many places that Windows OS is not considered at all, like this case:

void getTGAScreenShot(int nr)
{
    //...
    sprintf( buffer, "rm -f *__.tga %s",DEV_NULL);
    // ...
}

Now I understand why I had to copy rm.exe and mv.exe from C:\cygwin64\bin next to my CGX executable :slight_smile:

The CGX version 2.21 source code indicates that inpformat variable is set to 0 in the case of -bg mode:


      else if( compare( argv[j], "-bg", 3 ) == 3 )
      { 
        // ...
        inpformat=0;
        // ...
      }

And then, screenshot creation is skipped altogether if inpformat is set to 0 like this:

void createHardcopy( int selection, char *filePtr )
{

  if(!inpformat) return;

  // ...
}

Also here:

void getTGAScreenShot(int nr)
{

    if(!inpformat) return;

    // ...
}

Maybe send a patch to Klaus Wittig?

With OpenGL it is possible to set up an off-screen render context. So it could probably be done. Although I donā€™t know if that functionality is available on all platforms that cgx runs on. The question then is also how big to make that image? That should probably be made configurable as well.

1 Like

Good idea :+1:

Thanks. Iā€™m going to research that :books:

Maybe just Windows OS is enough for me at this point.

Right :white_check_mark: The window size should be configured.

If it is an option, maybe you can run cgx on a Linux machine and use the virtual frame buffer Xvfb. This allows to run graphical applications without a screen attached. It has come in handy for me in the past, although I have not tested with cgx.

It should be than as easy as running ā€˜xvfb-run cgx -b [frd]ā€™

If you run into issues with OpenGL, you may find some pointers on Stackoverflow: opengl es - GLX offscreen rendering in headless system - Stack Overflow

Iā€™m not aware of similar options for Windows thoughā€¦

Edit: just tried, using Xvfb works for me on Linux.

2 Likes