Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #define APPID 1234567
- // Comment the STOREFRAGMENT define to have a pixel-by-pixel copy in the BMUpdateCallback
- #define STOREFRAGMENT
- #include <windows.h>
- #include <iostream>
- using namespace std;
- #include "c4d_file.h"
- #include "default_alien_overloads.h"
- #include "c4d_renderconnection.h"
- using namespace melange;
- class RenderThread : public IpCommunicationThread
- {
- public:
- virtual void Main(void);
- };
- RenderThread *renderThread = nullptr;
- //----------------------------------------------------------------------------------------
- /// Helper function to convert float values returned by the renderer when COLORRESOLUTION_FLOAT is specified to [0..255] range
- /// @param[in] f Floating point value returned by the renderer
- /// @return Clamped component value between 0 and 255.
- //----------------------------------------------------------------------------------------
- static Int32 ConvFtoInt32 (Float f)
- {
- Int32 res = SAFEINT32(f * 256);
- if (f < 0.0)
- res = 0;
- else if (f > 255.0)
- res = 255;
- return res;
- }
- //----------------------------------------------------------------------------------------
- /// Framebuffer update callback.
- /// @param[in] userdata Pointer to the raw framebuffer structure. Can be @formatConstant{nullptr}. @callerOwnsPointed{data}
- /// @param[in] xpos Starting X-position of the RGBA data.
- /// @param[in] ypos Starting Y-position of the RGBA data.
- /// @param[in] xcnt The number of pixels of the image buffer.
- /// @param[in] bpp The color depth of the RGBA image.
- /// @param[in] rgba_data Contains the RGBA image data (4 bytes per pixel).
- //----------------------------------------------------------------------------------------
- void BMUpdateCallback(void *userdata, Int32 xpos, Int32 ypos, Int32 xcnt, ColorResolution bpp, UChar *rgba_data)
- {
- // Check the pointer to the raw framebuffer struct.
- if (!userdata)
- return;
- // Cast the void pointer to a framebuffer struct pointer.
- //framebuffer* fb = static_cast<framebuffer*>(userdata);
- BaseBitmap* bm = static_cast<BaseBitmap*>(userdata);
- // Save as const width and height of the image saved in the fb struct.
- //const Int32 xres = fb->xres;
- const Int32 xres = bm->GetBw();
- //const Int32 yres = fb->yres;
- const Int32 yres = bm->GetBh();
- // Check image sizes and pointer to the raw buffer.
- if (ypos < 0 || ypos >= yres)
- return;
- if (xpos + xcnt > xres)
- xcnt = xres - xpos;
- // Store the data to the bitmap accordingly to the type provided to the callback (float or uchar)
- if (bpp == 4)
- {
- // Floating point data is streamed and since it should be clamped to [0..255] range
- // the data should be converted for each pixel
- float *src = (float*)rgba_data;
- Int32 r, g, b;
- for (Int32 i = 0; i < xcnt; i++)
- {
- r = ConvFtoInt32(src[0]);
- g = ConvFtoInt32(src[1]);
- b = ConvFtoInt32(src[2]);
- bm->SetPixel(i + xpos, ypos, r, g, b);
- src += 4;
- }
- }
- else
- {
- // Unsigned char data is streamed so direct copy can be achieved
- bm->SetPixelCnt(xpos, ypos, xcnt, rgba_data, 4, COLORMODE_RGB, PIXELCNT_0);
- }
- }
- // Implementation of GetWriterInfo to return the exchange / external application ID and name.
- void GetWriterInfo(Int32 &id, String &appname)
- {
- id = APPID;
- appname = "SimpleStandaloneRendererConnection";
- }
- // Implementation the Main() method of the RenderThread with the desired functionality.
- void RenderThread::Main(void)
- {
- cout << "Rendering thread started." << endl;
- // Path to the scene to render.
- const String renderedFile = "testscene.c4d";
- // Load the scene document.
- BaseDocument *c4dDoc = LoadDocument(renderedFile, SCENEFILTER_OBJECTS);
- if (!c4dDoc)
- return;
- // Retrieve the first render data set.
- RenderData *rdata = c4dDoc->GetFirstRenderData();
- if (!rdata)
- return;
- // Allocate a BaseBitmap struct.
- BaseBitmap* bitmap = NewObj(BaseBitmap);
- if (nullptr == bitmap)
- return;
- //Retrieve the render info from the render settings and save in the framebuffer struct members.
- GeData data;
- rdata->GetParameter(RDATA_XRES, data);
- const Int32 xres = data.GetInt32();
- rdata->GetParameter(RDATA_YRES, data);
- const Int32 yres = data.GetInt32();
- // Initialize the BaseBitmap instance with the info just retrieved.
- bitmap->Init(xres, yres);
- // Initialize some render related variables.
- Int32 rendererror = RENDERERROR_OK, renderphase = PROGRESSTYPE_BEFORERENDERING;
- Float percent_done = 0.0;
- Bool running = true;
- // Open communication to the server
- if (!Open(nullptr, APPID, 100, 500))
- {
- return;
- }
- // Send the scene to the renderer.
- if (!SendScenefile(renderedFile))
- {
- cout << "No .c4d file found!" << endl;
- return;
- }
- // Start the rendering process.
- // Change the COLORRESOLUTION flag to switch from float to unsigned char and vice versa.
- if (!StartRender(xres, yres, COLORRESOLUTION_FLOAT, false, false))
- return;
- // Get the render image and progress while rendering.
- while (!TestBreak() && running)
- {
- // Update the image through the callback while rendering is running
- if (!GetImageUpdate(BMUpdateCallback, (void*)bitmap, &running))
- {
- rendererror = RENDERERROR_CONNECTIONFAILED;
- break;
- }
- // Get the status of the rendering process while rendering is running
- if (!GetRenderStatus(nullptr, &rendererror, &percent_done, &renderphase))
- {
- rendererror = RENDERERROR_CONNECTIONFAILED;
- break;
- }
- // Provide information and progress of each single rendering phase.
- // (The percentage always refer to the single rendering phase.)
- if (renderphase == PROGRESSTYPE_DURINGRENDERING)
- cout << "Rendering... " << percent_done * 100.0 << "%" << endl;
- else if (renderphase == PROGRESSTYPE_BEFORERENDERING)
- cout << "Preparing... " << percent_done * 100.0 << "%" << endl;
- else if (renderphase == PROGRESSTYPE_GLOBALILLUMINATION)
- cout << "Calculating Global Illumination... " << percent_done * 100.0 << "%" << endl;
- else if (renderphase == PROGRESSTYPE_AFTERRENDERING)
- cout << "Finishing... " << percent_done * 100.0 << "%" << endl;
- else if (renderphase == PROGRESSTYPE_QUICK_PREVIEW)
- cout << "Quick Preview... " << percent_done * 100.0 << "%" << endl;
- // Update every 10 ms to see percentage increase even on very simple scenes.
- if (running)
- GeSleep(10);
- }
- // Provide final information about the rendering process.
- if (rendererror != RENDERERROR_OK)
- cout << "Rendering failed." << endl;
- else
- cout << "Rendering finished." << endl;
- // Wait a little more to complete framebuffer fill-up.
- GeSleep(500);
- // Write to a simple file format.
- IMAGERESULT res = bitmap->Save("testrender.jpg", FILTER_JPG, nullptr, SAVEBIT_0);
- if (res == IMAGERESULT_OK)
- cout << "Image saved on disk.";
- else
- cout << "Failed to save image on disk.";
- // Deallocate the BaseBitmap instance
- DeleteObj(bitmap);
- //Free the session on the server.
- FreeSession();
- // Close the thread.
- Close(true);
- cout << "Rendering thread completed." << endl;
- }
- int main(int argc, Char* argv[])
- {
- // Init Melange threads
- GeInitThreads();
- // Init Melange communication
- GeIpInitNetwork();
- const String PathToCinema = "C:\\C4D\\17.053_RB166656\\CINEMA 4D.exe";
- // Start CINEMA in render server mode
- if (!StartRenderServer(PathToCinema, 1234))
- {
- cout << "CINEMA failed to start as a render server." << endl;
- return 0;
- }
- // Instantiate the RenderThread object.
- renderThread = NewObj(RenderThread);
- // Start the RenderThread instance.
- renderThread->Start(true);
- // Wait for the render thread to complete is job.
- while (renderThread->IsRunning());
- // Deallocate the RenderThread object.
- DeleteObj(renderThread);
- //Uninit Melange communication.
- GeIpCloseNetwork();
- //Uninit Melange thread.
- GeEndThreads();
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement