KnickKnack

Melange renderer connection standalone application

Sep 23rd, 2016
101
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #define APPID 1234567
  2.  
  3. // Comment the STOREFRAGMENT define to have a pixel-by-pixel copy in the BMUpdateCallback
  4. #define STOREFRAGMENT
  5.  
  6. #include <windows.h>
  7. #include <iostream>
  8. using namespace std;
  9.  
  10. #include "c4d_file.h"
  11. #include "default_alien_overloads.h"
  12. #include "c4d_renderconnection.h"
  13. using namespace melange;
  14.  
  15. class RenderThread : public IpCommunicationThread
  16. {
  17. public:
  18.     virtual void Main(void);
  19. };
  20.  
  21. RenderThread *renderThread = nullptr;
  22.  
  23.  
  24. //----------------------------------------------------------------------------------------
  25. /// Helper function to convert float values returned by the renderer when COLORRESOLUTION_FLOAT is specified to [0..255] range
  26. /// @param[in] f                                Floating point value returned by the renderer
  27. /// @return                                         Clamped component value between 0 and 255.
  28. //----------------------------------------------------------------------------------------
  29. static Int32 ConvFtoInt32 (Float f)
  30. {
  31.     Int32 res = SAFEINT32(f * 256);
  32.     if (f < 0.0)
  33.         res = 0;
  34.     else if (f > 255.0)
  35.         res =  255;
  36.     return res;
  37. }
  38.  
  39. //----------------------------------------------------------------------------------------
  40. /// Framebuffer update callback.
  41. /// @param[in] userdata                     Pointer to the raw framebuffer structure. Can be @formatConstant{nullptr}. @callerOwnsPointed{data}
  42. /// @param[in] xpos                             Starting X-position of the RGBA data.
  43. /// @param[in] ypos                             Starting Y-position of the RGBA data.
  44. /// @param[in] xcnt                             The number of pixels of the image buffer.
  45. /// @param[in] bpp                              The color depth of the RGBA image.
  46. /// @param[in] rgba_data                    Contains the RGBA image data (4 bytes per pixel).
  47. //----------------------------------------------------------------------------------------
  48. void BMUpdateCallback(void *userdata, Int32 xpos, Int32 ypos, Int32 xcnt, ColorResolution bpp, UChar *rgba_data)
  49. {
  50.     // Check the pointer to the raw framebuffer struct.
  51.     if (!userdata)
  52.         return;
  53.  
  54.     // Cast the void pointer to a framebuffer struct pointer.
  55.     //framebuffer* fb = static_cast<framebuffer*>(userdata);
  56.     BaseBitmap* bm = static_cast<BaseBitmap*>(userdata);
  57.  
  58.     // Save as const width and height of the image saved in the fb struct.
  59.     //const Int32 xres = fb->xres;
  60.     const Int32 xres = bm->GetBw();
  61.     //const Int32 yres = fb->yres;
  62.     const Int32 yres = bm->GetBh();
  63.  
  64.     // Check image sizes and pointer to the raw buffer.
  65.     if (ypos < 0 || ypos >= yres)
  66.         return;
  67.     if (xpos + xcnt > xres)
  68.         xcnt = xres - xpos;
  69.  
  70.     // Store the data to the bitmap accordingly to the type provided to the callback (float or uchar)
  71.     if (bpp == 4)
  72.     {
  73.         // Floating point data is streamed and since it should be clamped to [0..255] range
  74.         // the data should be converted for each pixel
  75.         float *src = (float*)rgba_data;
  76.         Int32 r, g, b;
  77.         for (Int32 i = 0; i < xcnt; i++)
  78.         {
  79.             r = ConvFtoInt32(src[0]);
  80.             g = ConvFtoInt32(src[1]);
  81.             b = ConvFtoInt32(src[2]);
  82.             bm->SetPixel(i + xpos, ypos, r, g, b);
  83.             src += 4;
  84.         }
  85.     }
  86.     else
  87.     {  
  88.         // Unsigned char data is streamed so direct copy can be achieved
  89.         bm->SetPixelCnt(xpos, ypos, xcnt, rgba_data, 4, COLORMODE_RGB, PIXELCNT_0);
  90.     }
  91. }
  92.  
  93.  
  94. // Implementation of GetWriterInfo to return the exchange / external application ID and name.
  95. void GetWriterInfo(Int32 &id, String &appname)
  96. {
  97.     id = APPID;
  98.     appname = "SimpleStandaloneRendererConnection";
  99. }
  100.  
  101. // Implementation the Main() method of the RenderThread with the desired functionality.
  102. void RenderThread::Main(void)
  103. {
  104.     cout << "Rendering thread started." << endl;
  105.  
  106.     // Path to the scene to render.
  107.     const String renderedFile = "testscene.c4d";
  108.  
  109.     // Load the scene document.
  110.     BaseDocument *c4dDoc = LoadDocument(renderedFile, SCENEFILTER_OBJECTS);
  111.     if (!c4dDoc)
  112.         return;
  113.  
  114.     // Retrieve the first render data set.
  115.     RenderData *rdata = c4dDoc->GetFirstRenderData();
  116.     if (!rdata)
  117.         return;
  118.    
  119.     // Allocate a BaseBitmap struct.
  120.     BaseBitmap* bitmap = NewObj(BaseBitmap);
  121.     if (nullptr == bitmap)
  122.         return;
  123.        
  124.     //Retrieve the render info from the render settings and save in the framebuffer struct members.
  125.     GeData data;
  126.     rdata->GetParameter(RDATA_XRES, data);
  127.     const Int32 xres = data.GetInt32();
  128.     rdata->GetParameter(RDATA_YRES, data);
  129.     const Int32 yres = data.GetInt32();
  130.  
  131.     // Initialize the BaseBitmap instance with the info just retrieved.
  132.     bitmap->Init(xres, yres);
  133.  
  134.     // Initialize some render related variables.
  135.     Int32 rendererror = RENDERERROR_OK, renderphase = PROGRESSTYPE_BEFORERENDERING;
  136.     Float percent_done = 0.0;
  137.     Bool running = true;
  138.  
  139.     // Open communication to the server
  140.     if (!Open(nullptr, APPID, 100, 500))
  141.     {
  142.         return;
  143.     }
  144.  
  145.     // Send the scene to the renderer.
  146.     if (!SendScenefile(renderedFile))
  147.     {
  148.         cout << "No .c4d file found!" << endl;
  149.         return;
  150.     }
  151.  
  152.     // Start the rendering process.
  153.     // Change the COLORRESOLUTION flag to switch from float to unsigned char and vice versa.
  154.     if (!StartRender(xres, yres, COLORRESOLUTION_FLOAT, false, false))
  155.         return;
  156.  
  157.     // Get the render image and progress while rendering.
  158.     while (!TestBreak() && running)
  159.     {
  160.         // Update the image through the callback while rendering is running
  161.         if (!GetImageUpdate(BMUpdateCallback, (void*)bitmap, &running))
  162.         {
  163.             rendererror = RENDERERROR_CONNECTIONFAILED;
  164.             break;
  165.         }
  166.         // Get the status of the rendering process while rendering is running
  167.         if (!GetRenderStatus(nullptr, &rendererror, &percent_done, &renderphase))
  168.         {
  169.             rendererror = RENDERERROR_CONNECTIONFAILED;
  170.             break;
  171.         }
  172.  
  173.         // Provide information and progress of each single rendering phase.
  174.         // (The percentage always refer to the single rendering phase.)
  175.         if (renderphase == PROGRESSTYPE_DURINGRENDERING)
  176.             cout << "Rendering... " << percent_done * 100.0 << "%" << endl;
  177.         else if (renderphase == PROGRESSTYPE_BEFORERENDERING)
  178.             cout << "Preparing... " << percent_done * 100.0 << "%" << endl;
  179.         else if (renderphase == PROGRESSTYPE_GLOBALILLUMINATION)
  180.             cout << "Calculating Global Illumination... " << percent_done * 100.0 << "%" << endl;
  181.         else if (renderphase == PROGRESSTYPE_AFTERRENDERING)
  182.             cout << "Finishing... " << percent_done * 100.0 << "%" << endl;
  183.         else if (renderphase == PROGRESSTYPE_QUICK_PREVIEW)
  184.             cout << "Quick Preview... " << percent_done * 100.0 << "%" << endl;
  185.        
  186.         // Update every 10 ms to see percentage increase even on very simple scenes.
  187.         if (running)
  188.             GeSleep(10);
  189.     }
  190.  
  191.     // Provide final information about the rendering process.
  192.     if (rendererror != RENDERERROR_OK)
  193.         cout << "Rendering failed." << endl;
  194.     else
  195.         cout << "Rendering finished." << endl;
  196.  
  197.     // Wait a little more to complete framebuffer fill-up.
  198.     GeSleep(500);
  199.  
  200.     // Write to a simple file format.
  201.     IMAGERESULT res =  bitmap->Save("testrender.jpg", FILTER_JPG, nullptr, SAVEBIT_0);
  202.  
  203.     if (res == IMAGERESULT_OK)
  204.         cout << "Image saved on disk.";
  205.     else
  206.         cout << "Failed to save image on disk.";
  207.        
  208.     // Deallocate the BaseBitmap instance
  209.     DeleteObj(bitmap);
  210.  
  211.     //Free the session on the server.
  212.     FreeSession();
  213.  
  214.     // Close the thread.
  215.     Close(true);
  216.  
  217.     cout << "Rendering thread completed." << endl;
  218. }
  219.  
  220. int main(int argc, Char* argv[])
  221. {
  222.     // Init Melange threads
  223.     GeInitThreads();
  224.  
  225.     // Init Melange communication
  226.     GeIpInitNetwork();
  227.    
  228.     const String PathToCinema = "C:\\C4D\\17.053_RB166656\\CINEMA 4D.exe";
  229.  
  230.     // Start CINEMA in render server mode
  231.     if (!StartRenderServer(PathToCinema, 1234))
  232.     {
  233.         cout << "CINEMA failed to start as a render server." << endl;
  234.         return 0;
  235.     }
  236.  
  237.     // Instantiate the RenderThread object.
  238.     renderThread = NewObj(RenderThread);
  239.  
  240.     // Start the RenderThread instance.
  241.     renderThread->Start(true);
  242.  
  243.     // Wait for the render thread to complete is job.
  244.     while (renderThread->IsRunning());
  245.    
  246.     // Deallocate the RenderThread object.
  247.     DeleteObj(renderThread);
  248.  
  249.     //Uninit Melange communication.
  250.     GeIpCloseNetwork();
  251.  
  252.     //Uninit Melange thread.
  253.     GeEndThreads();
  254.    
  255.     return 0;
  256. }
RAW Paste Data