Fri, 03/22/2024 - 18:54
Good afternoon,
Currently I am building a small piece of code to make pictures of .stp files. The code will run on a system without any gpu/graphics, so I am trying to use the mesa3d software implementation of OpenGL. The code works, but when i call the method that creates a screenshot a second time, i get an exception:
Microsoft C++ exception: Aspect_GraphicDeviceDefinitionError at memory location ...
The exception is thrown by the line "view->SetBackgroundColor(Quantity_Color(Quantity_NOC_WHITE));"
When I print the message of the exception, the following is shown:
OpenGl_Window::CreateWindow: SetPixelFormat failed. Error code: 0
This is the code:
unsigned char* dumpShape(const TopoDS_Shape& shape, const Standard_Integer width, const Standard_Integer height)
{
// prepare viewer
Handle(Aspect_DisplayConnection) displayConnection = new Aspect_DisplayConnection();
Handle(OpenGl_GraphicDriver) graphicDriver = new OpenGl_GraphicDriver(displayConnection);
Handle(V3d_Viewer) viewer = new V3d_Viewer(graphicDriver);
viewer->SetDefaultLights();
viewer->SetLightOn();
Handle(AIS_InteractiveContext) context = new AIS_InteractiveContext(viewer);
// prepare off-screen view
Handle(V3d_View) view = viewer->CreateView();
Handle(Aspect_NeutralWindow) wnd = new Aspect_NeutralWindow();
wnd->SetSize(width, height);
wnd->SetVirtual(true);
view->SetWindow(wnd);
view->SetBackgroundColor(Quantity_Color(Quantity_NOC_WHITE));
view->MustBeResized();
// prepare presentation filled by shape
Handle(AIS_Shape) presentation = new AIS_Shape(shape);
context->Display(presentation, Standard_False);
context->SetDisplayMode(presentation, AIS_Shaded, Standard_False);
view->FitAll();
view->Redraw();
// prepare pixmap image
Image_AlienPixMap img;
if (!view->ToPixMap(img, width, height))
return nullptr;
const Standard_Byte* bytes_img = img.Data();
// Calculate the size of the image data
int dataSize = width * height * 3; // Assuming 24-bit RGB data (3 bytes per pixel)
// Allocate memory for the image data
unsigned char* imageData = new unsigned char[dataSize];
// imageData byte array
for (int i = 0; i < width; ++i) {
for (int j = 0; j < height; ++j) {
// Calculate the index in bytes_img
int index = i * width + j;
imageData[index * 3] = static_cast<unsigned char>(bytes_img[index * 3 + 2]); // Blue
imageData[index * 3 + 1] = static_cast<unsigned char>(bytes_img[index * 3 + 1]); // Green
imageData[index * 3 + 2] = static_cast<unsigned char>(bytes_img[index * 3]); // Red
}
return imageData;
}
return nullptr;
}
bool ImgFromStep(const char* stpContent, unsigned char** imageDataPtr)
{
StepFileReader sfr;
const TopoDS_Shape& shape = sfr.ShapeFromFile(stpContent);
unsigned char* newImageData = dumpShape(shape, 600, 600);
unsigned char* newImageData2 = dumpShape(shape, 600, 600); //This second method call makes the program crash.
*imageDataPtr = newImageData;
return true;
}
Some additional information:
-OpenCascade version 7.8
-mesa-llvmpipe-24.0.3 (opengl32.dll taken from https://github.com/mmozeiko/build-mesa/releases/tag/24.0.3 and extracted next to the .exe of my program. Without this mesa opengl32.dll, the program runs fine.)
-Although the viewer should be hidden, some weird squares/pieces of the viewer are displayed during the first dumpShape call.
I'm wondering if you could point me in the right direction, I don't think opencascade is the problem, but (my use of) mesa.
If you need any additional information, let me know!
Thank you in advance!
Martijn
Fri, 03/22/2024 - 22:19
Here you are setting to View a Window that have undefined zero window id (
Aspect_NeutralWindow::SetNativeHandle
is not called):Even if you are using a 'virtual' window and use software OpenGL implementation - you still need to create a valid platform-dependent window for that. There is a code sample how this could be done. There might be a way to use completely offscreen rendering in case of a Mesa library, but OCCT doesn't know about it when you just replace
opengl32.dll
library.I guess that some mess happens when you pass 0 window id to OpenGL on Windows platform, like drawing into Desktop window or something like this - this would clarify why you are able to create a first screenshot and why something appears on the screen.