void ArnoldAnimationPatch::renderSingleFrame(const set<Device*>& devices, string basepath, string filename) { if (m_mode != SimulationAnimationMode::STOPPED) disableContinuousRenderMode(); FrameDeviceInfo frame; // Fulls time and mode for frame info. createFrameInfoHeader(frame); createFrameInfoBody(devices, frame); std::stringstream ss; ss << "Rendering single frame: " << frame.time; Logger::log(LDEBUG, ss.str()); // Interrupts the current rendering if in the interactive mode. if (m_mode == SimulationAnimationMode::INTERACTIVE || m_mode == SimulationAnimationMode::RECORDING) { interruptRender(); } // Render immediately. if (!m_interface->isDistributedOpen()) { m_interface->init(this->toJSON()); // Check if we were able to open a connection if (!m_interface->isDistributedOpen()) { std::cerr << "Connection could not be established. " << "Check to make sure your host and port " << "parameters are correct and that nobody " << "else is currently using the remote renderer" << std::endl; return; } } bool success = false; float* bp = nullptr; int cid; int w = getWidth(); int h = getHeight(); if (CachingArnoldInterface* ci = dynamic_cast<CachingArnoldInterface*>(m_interface)) { #ifdef USE_ARNOLD success = ci->render(devices, w, h, cid) == AI_SUCCESS; #else success = ci->render(devices, w, h, cid) == 0; #endif // we need to pull the proper buffer from the right context bp = ci->getBufferForContext(cid); frame.clear(); } else { updateLight(devices); success = ArnoldPatch::renderLoop(devices); frame.clear(); bp = getBufferPointer(); } if (success) { unsigned char *bytes = new unsigned char[w * h * 4]; floats_to_bytes(bytes, bp, w, h); string file = basepath + "/" + filename + ".png"; if (!imageio_save_image(file.c_str(), bytes, getWidth(), getHeight())) { std::stringstream err_ss; err_ss << "Error to write png: " << filename; Logger::log(ERR, err_ss.str()); } } if (CachingArnoldInterface* ci = dynamic_cast<CachingArnoldInterface*>(m_interface)) { ci->closeContext(cid); } }
void ArnoldAnimationPatch::renderSingleFrameToBuffer(const set<Device*>& devices, unsigned char* buff, int w, int h) { if (m_mode != SimulationAnimationMode::STOPPED) disableContinuousRenderMode(); FrameDeviceInfo frame; // Fulls time and mode for frame info. createFrameInfoHeader(frame); createFrameInfoBody(devices, frame, true); std::stringstream ss; ss << "Rendering single frame: " << frame.time; Logger::log(LDEBUG, ss.str()); // Interrupts the current rendering if in the interactive mode. if (m_mode == SimulationAnimationMode::INTERACTIVE || m_mode == SimulationAnimationMode::RECORDING) { interruptRender(); } // Render immediately. if (!m_interface->isDistributedOpen()) { m_interface->init(this->toJSON()); // Check if we were able to open a connection if (!m_interface->isDistributedOpen()) { std::cerr << "Connection could not be established. " << "Check to make sure your host and port " << "parameters are correct and that nobody " << "else is currently using the remote renderer" << std::endl; return; } } bool success = false; float* bp = nullptr; int cid; if (CachingArnoldInterface* ci = dynamic_cast<CachingArnoldInterface*>(m_interface)) { #ifdef USE_ARNOLD success = ci->render(devices, w, h, cid) == AI_SUCCESS; #else success = ci->render(devices, w, h, cid) == 0; #endif // we need to pull the proper buffer from the right context bp = ci->getBufferForContext(cid); frame.clear(); } else { updateLight(devices); success = ArnoldPatch::renderLoop(devices); frame.clear(); bp = getBufferPointer(); } if (success) { for (int j = 0; j < h; j++) { for (int i = 0; i < w; i++) { int offset = (j * w + i) * 4; // convert to bytes buff[offset] = static_cast<unsigned char>(bp[offset + 2] * 0xff); buff[offset + 1] = static_cast<unsigned char>(bp[offset + 1] * 0xff); buff[offset + 2] = static_cast<unsigned char>(bp[offset + 0] * 0xff); buff[offset + 3] = static_cast<unsigned char>(bp[offset + 3] * 0xff); } } } if (CachingArnoldInterface* ci = dynamic_cast<CachingArnoldInterface*>(m_interface)) { ci->closeContext(cid); } }
void SimulationAnimationPatch::workerLoop() { FrameDeviceInfo frame; while(1) { // Releases the lock immediately if the queue is still empty. while (frame.time < 0) { if (m_mode == SimulationAnimationMode::STOPPED) continue; m_queue.lock(); if (m_queuedFrameDeviceInfo.size() > 0) { if (m_mode == SimulationAnimationMode::RECORDING) { // Clears irrelated info std::vector<FrameDeviceInfo>::iterator i; for (i = m_queuedFrameDeviceInfo.begin(); i != m_queuedFrameDeviceInfo.end() && i->mode == SimulationAnimationMode::INTERACTIVE; i++) { i->clear(); } m_queuedFrameDeviceInfo.erase(m_queuedFrameDeviceInfo.begin(), i); // Deep copy (since we're going to clear it) for (i = m_queuedFrameDeviceInfo.begin(); i != m_queuedFrameDeviceInfo.end(); i++) { // Copies the last recording info to do preview if (i->mode == SimulationAnimationMode::RECORDING) { frame.copyByValue(*i); // Waits to be rendered with higher sampling rate i->mode = SimulationAnimationMode::RENDERING; } } } else if (m_mode == SimulationAnimationMode::RENDERING) { // No frame would be skipped. frame = m_queuedFrameDeviceInfo[0]; m_queuedFrameDeviceInfo.erase(m_queuedFrameDeviceInfo.begin()); } else if (m_mode == SimulationAnimationMode::INTERACTIVE) { frame = m_queuedFrameDeviceInfo.back(); for (FrameDeviceInfo &info : m_queuedFrameDeviceInfo) { if (info.time != m_queuedFrameDeviceInfo.back().time) info.clear(); } m_queuedFrameDeviceInfo.clear(); } } // No more frames for rendering else if (m_mode == SimulationAnimationMode::RENDERING) { onWorkerFinished(); } m_queue.unlock(); // The frame is valid. if (frame.time >= 0) { if (frame.mode == SimulationAnimationMode::STOPPED) { m_mode = SimulationAnimationMode::STOPPED; Logger::log(INFO, "Worker stopped..."); return ; } else if (frame.mode == SimulationAnimationMode::RECORDING) { onRecording(); } else if (frame.mode == SimulationAnimationMode::RENDERING) { onRendering(); } // Finished recording work else if (frame.mode == SimulationAnimationMode::INTERACTIVE && (m_mode == SimulationAnimationMode::RENDERING)) { onWorkerFinished(); } } } // Releases copies of devices. workerRender(frame); frame.clear(); } }