AntoineAB Posted Friday at 03:03 PM Share Posted Friday at 03:03 PM Hello, I am currently updating a code from SDK 2.16 to SDK 2.18.1. According to the SDK 2.17 migrations updates, this piece of code in 2.16 : // save texture to file ImagePtr image = Image::create(); texture->getImage(image); image->save(file_name); // apply texture to disk mesh if (object_dst->getNumSurfaces()>0) object_dst->setMaterialTexture(material_texture_name.get(), file_name.get(), 0); would be updated to : // save texture to file ImagePtr image = Image::create(); // synchronous Render::transferTextureToImage( MakeCallback([&](ImagePtr image) { image->save(file_name); }), texture); // apply texture to disk mesh if (object_dst->getNumSurfaces()>0) object_dst->setMaterialTexture(material_texture_name.get(), file_name.get(), 0); The code was working in 2.16 and now it is raising an exception in 2.18 (access violation exception) when the callback tries to read the variable file_name (this variable scope is the function where the callback is created). Is it normal ? if yes how should I change that code to make is work ? Best regards. Link to comment
bmyagkov Posted 5 hours ago Share Posted 5 hours ago Hello! On 6/28/2024 at 10:03 PM, AntoineAB said: The code was working in 2.16 and now it is raising an exception in 2.18 (access violation exception) when the callback tries to read the variable file_name (this variable scope is the function where the callback is created). Is it normal ? if yes how should I change that code to make is work ? You don't need to create an image variable because transferTextureToImage does it automatically and deletes it after the callback. Also, transferTextureToImage will be called with the swap at the end of this frame. So, if you need to save the image and then set the texture by path you should do it inside the callback. Otherwise, you can set the texture itself not by path. To do this you should get the material and use setTexture. For example: object_dst->getMaterial(0)->setTexture("name", texture); Thanks! Link to comment
AntoineAB Posted 1 hour ago Author Share Posted 1 hour ago Hello, Thank you for the information. But I still have the problem. I can't use local variables in the callback because they seem to be destroyed when the callback is called. Here is another example : void takeScreenshot::init() { std::stringstream stringStreamPath; stringStreamPath << GetImagesFolderPath(); // synchronous Render::transferTextureToImage( MakeCallback([&](ImagePtr image) { image->save(file_name); std::string filename = stringStreamPath.str(); image->save(filename.c_str()); Log::message("Screenshot saved to %s\n", filename.c_str()); }), texture); } Here, the problem is that the callback returns an exception (access violation exception) when it tries to read stringStreamPath. How could I use a variable in a callback that is created outside of a callback ? or is it the wrong way to do it ? Regards. Link to comment
bmyagkov Posted 33 minutes ago Share Posted 33 minutes ago You have declared the variable in the local scope (within the takeScreenshot::init function scope) so when the scope exits all local variables will be freed. Therefore, you need to declare stringStreamPath outside of the local scope (for instance in the takeScreenshot class) and then pass it as you already do; it shouldn't be destroyed. Additionally, don't assume that transferTextureToImage will call the callback immediately because it called "synchronous" because actually it will be called later in this frame. That's why your scope exits and local variables are cleared. Thanks! Link to comment
Recommended Posts