I am coding a app using Ogre where I need to update a dynamic texture. The update speed will be ~30fps, but I need that the main loop runs at ~120fps. I have a manager class that take the images from a camera, do some processing with OpenCV and so, update the texture. The texture is created by the core application and ist poiter is passed to the manager class.
If I call for the updateTexture method from de manager class inside the main loop, my fps is bound to the update speed of the manager class. I not want this. I need to run the main loop as fast as I can, but the texture will be updated at ~30fps.
I'm thinking on using a trhead to do de updating of the texture, but I am not so sure about what I have to do, so I'm seeking sugestions. Right now, I'm trying to implement threads using ptypes. I'm working on Linux now, but the code will be migrated to Windows, but keeping the portability.
The code of the updateTexture method:
Code: Select all
void VideoManager::updateTexture()
{
if (videoCapture->isOpened())
{
videoCapture->grab();
videoCapture->retrieve(frame, CV_CAP_OPENNI_BGR_IMAGE);
videoCapture->retrieve(depthMap, CV_CAP_OPENNI_DEPTH_MAP);
videoCapture->retrieve(disparityMap, CV_CAP_OPENNI_DISPARITY_MAP);
}
else return;
// Get the pixel buffer
mPixelBuffer = texturePtr->getBuffer();
// Lock the pixel buffer and get a pixel box
mPixelBuffer->lock(Ogre::HardwareBuffer::HBL_DISCARD); // for best performance use HBL_DISCARD!
const Ogre::PixelBox& mPixelBox = mPixelBuffer->getCurrentLock();
pDest = static_cast<Ogre::uchar*> (mPixelBox.data);
if (displayMode == RGB)
{
pSour = static_cast<Ogre::uchar*> (frame.data);
if (isMirrored)
{
for (size_t j = 0; j < mCapHeight; j++)
{
pSour += (mCapWidth - 1) * 3;
for (size_t i = 0; i < mCapWidth; i++)
{
*pDest++ = *pSour++; // B
*pDest++ = *pSour++; // G
*pDest++ = *pSour++; // R
*pDest++ = 0; // A
pSour -= 6; //2 * canais
}
pSour += (mCapWidth + 1) * 3;
}
}
else
{
for (size_t j = 0; j < mCapHeight; j++)
for (size_t i = 0; i < mCapWidth; i++)
{
*pDest++ = *pSour++; // B
*pDest++ = *pSour++; // G
*pDest++ = *pSour++; // R
*pDest++ = 0; // A
}
}
}
else if (displayMode == DEPTH)
{
const float scaleFactor = 0.05f;
cv::Mat show;
depthMap.convertTo(show, CV_8UC1, scaleFactor);
pSour = static_cast<Ogre::uchar*> (show.data);
if (isMirrored)
{
for (size_t j = 0; j < mCapHeight; j++)
{
pSour += (mCapWidth - 1);
for (size_t i = 0; i < mCapWidth; i++)
{
*pDest++ = *pSour; // B
*pDest++ = *pSour; // G
*pDest++ = *pSour++; // R
*pDest++ = 0; // A
pSour -= 2;
}
pSour += (mCapWidth + 1);
}
}
else
{
for (size_t j = 0; j < mCapHeight; j++)
for (size_t i = 0; i < mCapWidth; i++)
{
*pDest++ = *pSour; // B
*pDest++ = *pSour; // G
*pDest++ = *pSour++; // R
*pDest++ = 0; // A
}
}
}
else if (displayMode == DISPARITY)
{
pSour = static_cast<Ogre::uchar*> (disparityMap.data);
if (isMirrored)
{
for (size_t j = 0; j < mCapHeight; j++)
{
pSour += (mCapWidth - 1);
for (size_t i = 0; i < mCapWidth; i++)
{
*pDest++ = *pSour; // B
*pDest++ = *pSour; // G
*pDest++ = *pSour++; // R
*pDest++ = 0; // A
pSour -= 2;
}
pSour += (mCapWidth + 1);
}
}
else
{
for (size_t j = 0; j < mCapHeight; j++)
for (size_t i = 0; i < mCapWidth; i++)
{
*pDest++ = *pSour; // B
*pDest++ = *pSour; // G
*pDest++ = *pSour++; // R
*pDest++ = 0; // A
}
}
}
// Unlock the pixel buffer
mPixelBuffer->unlock();
}
Code: Select all
void OgreManager::mainLoop()
{
Ogre::LogManager::getSingletonPtr()->logMessage("*** Starting Main Loop ***");
frameTicker->reset();
while (stateManager->getCurrentState() != SHUTDOWN)
{
if (mainWindow->isClosed())
{
stateManager->requestStateChange(SHUTDOWN);
}
//Input Manager;
inputManager->capture();
Ogre::WindowEventUtilities::messagePump();
if (stateManager->getCurrentState() == GUI)
{
//Mostre a GUI
pGUIRenderer->setRenderingEnabled(true);
}
else if (stateManager->getCurrentState() == SIMULATION)
{
//Roda a simulação
pGUIRenderer->setRenderingEnabled(false);
if (videoOn) videoManager->updateTexture();
}
physicsManager->addStepSimulation(33);
ogreRoot->renderOneFrame();
frameTicker->reset();
}
QUICK UPDATE:
I encapsulated the updateTexture() method around the execute() method inherited by de pt::thread class from ptypes/pasync lib and it give me a segfault on the mPixelBuffer->unlock() call. Why it happened? I need to create the texture in the same trhead, maybe?
