#include "videoviewmixin.h"
#include "cameramanipulator.h"
#include "streammetatypecameracalibration.h"
#include <osg/FrameBufferObject>
#include <osg/GLExtensions>
#include <osg/PositionAttitudeTransform>
#include <osg/ShapeDrawable>
#include <osg/Texture2D>
#include <osg/Depth>
#define MIN(a, b) ((a) < (b) ? (a) : (b))
ADTF_PLUGIN_VERSION("Demo 3D Video View Mixin Plugin",
disptb,
DISPTB_VERSION_MAJOR,
DISPTB_VERSION_MINOR,
DISPTB_VERSION_PATCH,
cVideoViewMixin)
cVideoViewMixin::cVideoViewMixin()
{
m_bShowCameraSymbol.SetDescription("If enabled, camera will be added.");
RegisterPropertyVariable("show_camera_symbol", m_bShowCameraSymbol);
m_bKeepAspect.SetDescription("If enabled, aspect ratio will be kept.");
RegisterPropertyVariable("camera_window_aspect", m_bKeepAspect);
m_fFarClipping.SetDescription("Clipping value.");
RegisterPropertyVariable("camera_view_clipping_distance", m_fFarClipping);
m_strCameraConfigFile.SetDescription("Configuration settings for the camera.");
RegisterPropertyVariable("camera_config_file", m_strCameraConfigFile);
m_fVideoScreenDistance.SetDescription("Video screen distance.");
RegisterPropertyVariable("video_screen_distance", m_fVideoScreenDistance);
m_sVideo.pVideoReader = CreateInputPin("video", stream_meta_type_image());
adtf::streaming::set_description(*this, "video", "Input pin for the video data.");
m_sVideo.pCalibrationReader = CreateInputPin("calib", videoviewmixin::stream_meta_type_camera_calibration());
adtf::streaming::set_description(*this, "calib", "Input pin for camera calibration data.");
m_sVideo.pGCLReader = CreateInputPin("gcl", stream_meta_type_gcl());
adtf::streaming::set_description(*this, "gcl", "Input pin for GCL commands.");
SetDescription("Use this Mixin to create a canvas for showing a video in the scene.");
adtf::streaming::set_help_link(*this, "$(ADTF_DISPLAY_TOOLBOX_DIR)/doc/displaytoolbox_html/page_3d_videoview_mixin_example_readme.html");
ref();
}
cVideoViewMixin::~cVideoViewMixin()
{
unref_nodelete();
}
tResult cVideoViewMixin::InitScene()
{
RETURN_IF_FAILED(cMixin::InitScene());
RETURN_IF_FAILED(GetSceneGraph().GetObject(m_pIViewer));
m_pViewer = m_pIViewer->GetOsgViewer();
m_bUseFBO = osg::GLExtensions::Get(m_pIViewer->GetContextId(), true)->isFrameBufferObjectSupported;
if (m_bUseFBO)
{
LOG_INFO("using FBOs for rendering to texture in GCL mode");
}
else
{
LOG_INFO("using framebuffer for rendering to texture in GCL mode");
}
m_sVideo.bCameraView = tFalse;
m_sVideo.bShowVideo = tTrue;
m_sVideo.sFormat =
{
320,
240,
8,
IImage::PF_GREYSCALE_8,
320,
320 * 240,
0
};
CreateVideoWall();
m_pViewer->addEventHandler(this);
m_pExtDrawCallback = new cExtDrawCallback(this, m_pViewer->getCamera()->getInitialDrawCallback());
m_pViewer->getCamera()->setInitialDrawCallback(m_pExtDrawCallback);
m_bSceneReady = tTrue;
RETURN_NOERROR;
}
tVoid cVideoViewMixin::ClearScene()
{
if (GetRoot())
{
GetRoot()->removeChildren(0, GetRoot()->getNumChildren());
}
if (m_pExtDrawCallback)
{
m_pExtDrawCallback->m_pPrevious = nullptr;
}
if (m_pViewer)
{
m_pViewer->removeEventHandler(this);
}
}
tResult cVideoViewMixin::CreateVideoWall()
{
m_sVideo.bFormatChanged = tFalse;
tBool bUseGCL = m_sVideo.bUseGCL;
tBool bOldShowVideo = m_sVideo.bShowVideo;
tBool bOldCameraView = m_sVideo.bCameraView;
if (bOldCameraView)
{
SetCameraView(tFalse);
}
GetRoot()->removeChild(m_sVideo.pTransform);
m_sVideo.pTransform = nullptr;
m_sVideo.pCam = nullptr;
m_sVideo.pGCL = nullptr;
m_sVideo.pGCLCam = nullptr;
m_sVideo.pImage = nullptr;
m_sVideo.pVideo = nullptr;
m_sVideo.pVideoGeometry = nullptr;
m_sVideo.pVideoState = nullptr;
m_sVideo.oCamera.m_nResX = 0.0;
if (m_strCameraConfigFile->IsNotEmpty())
{
RETURN_IF_FAILED(m_sVideo.oCamera.ParseConfig(m_strCameraConfigFile));
}
m_sVideo.bConvertToRGB = tFalse;
if (m_sVideo.sFormat.nPixelFormat == cImage::PF_UNKNOWN)
{
LOG_WARNING("%s: the input pixel format is unkown, trying to guess it.");
m_sVideo.sFormat.nPixelFormat = cImage::GuessPixelFormat(&m_sVideo.sFormat);
if (m_sVideo.sFormat.nPixelFormat == cImage::PF_UNKNOWN)
{
LOG_WARNING("Unable to guess pixel format, waiting for media type change.");
RETURN_NOERROR;
}
}
if (m_sVideo.sFormat.nPixelFormat == cImage::PF_YUV420P_888 &&
m_sVideo.sFormat.nBitsPerPixel == 24)
{
m_sVideo.bConvertToRGB = tTrue;
m_sVideo.nPixelType = GL_UNSIGNED_BYTE;
m_sVideo.nBitmapFormat = GL_BGR;
m_sVideo.nBitmapFormatInternal = GL_RGB;
}
else
{
if (IS_FAILED(cGLTexture::CalcOpenGLTextureFormat(&m_sVideo.sFormat,
&m_sVideo.nPixelType,
&m_sVideo.nBitmapFormat,
&m_sVideo.nBitmapFormatInternal)))
{
LOG_WARNING("Unsupported PixelFormat %d with %d bits per pixel, waiting for media type change.", m_sVideo.sFormat.nPixelFormat, m_sVideo.sFormat.nBitsPerPixel);
RETURN_NOERROR;
}
}
m_sVideo.pImage = new osg::Image;
m_sVideo.pImage->setPixelBufferObject(new osg::PixelBufferObject(m_sVideo.pImage.get()));
if (m_sVideo.oCamera.m_nResX == 0)
{
m_sVideo.oCamera.m_nResX = m_sVideo.sFormat.nWidth;
m_sVideo.oCamera.m_nResY = m_sVideo.sFormat.nHeight;
m_sVideo.oCamera.m_fPrincipalX = m_sVideo.oCamera.m_nResX / 2.0;
m_sVideo.oCamera.m_fPrincipalY = m_sVideo.oCamera.m_nResY / 2.0;
m_sVideo.oCamera.m_fFocalX = m_sVideo.oCamera.m_fFocalY = m_sVideo.oCamera.m_nResX;
}
m_sVideo.pTransform = new osg::PositionAttitudeTransform;
GetRoot()->addChild(m_sVideo.pTransform);
m_sVideo.pTransform->addChild(new osg::Node);
{
m_sVideo.pCam = new osg::Geode;
if (m_bShowCameraSymbol)
{
m_sVideo.pTransform->addChild(m_sVideo.pCam.get());
}
osg::Vec4 oColor(1.0f, 0.0f, 0.0f, 1.0f);
osg::Box* pCamBox = new osg::Box(osg::Vec3(0, 0, 0), 1.0f);
osg::ShapeDrawable* pCamBoxDrawable = new osg::ShapeDrawable(pCamBox);
pCamBoxDrawable->setColor(oColor);
m_sVideo.pCam->addDrawable(pCamBoxDrawable);
osg::Cone* pCamCone = new osg::Cone(osg::Vec3(0.75f, 0, 0), 0.6f, 1.0f);
pCamCone->setRotation(osg::Quat(-M_PI_2, osg::Vec3(0, 1, 0)));
osg::ShapeDrawable* pCamConeDrawable = new osg::ShapeDrawable(pCamCone);
pCamConeDrawable->setColor(oColor);
m_sVideo.pCam->addDrawable(pCamConeDrawable);
}
{
m_sVideo.bCameraView = tFalse;
m_sVideo.bShowVideo = tTrue;
m_sVideo.pVideo = new osg::Geode;
m_sVideo.pTransform->addChild(m_sVideo.pVideo.get());
m_sVideo.pVideoGeometry = new osg::Geometry;
m_sVideo.pVideo->addDrawable(m_sVideo.pVideoGeometry.get());
osg::Vec4Array* pColors = new osg::Vec4Array;
osg::Vec3Array* pNormals = new osg::Vec3Array;
m_sVideo.fScreenDist = m_fVideoScreenDistance;
pNormals->push_back(osg::Vec3(-1, 0, 0));
pColors->push_back(osg::Vec4(1, 1, 1, 1));
m_sVideo.pVideoGeometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS, 0, 4));
m_sVideo.pVideoGeometry->setColorArray(pColors, osg::Array::BIND_PER_PRIMITIVE_SET);
m_sVideo.pVideoGeometry->setNormalArray(pNormals, osg::Array::BIND_PER_PRIMITIVE_SET);
UpdateCamAndScreen();
m_sVideo.pVideoState = new osg::StateSet();
m_sVideo.pVideoState->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
m_sVideo.pVideo->setStateSet(m_sVideo.pVideoState.get());
}
{
osg::Texture2D* pVideoTexture;
pVideoTexture = new osg::Texture2D;
pVideoTexture->setDataVariance(osg::Object::DYNAMIC);
pVideoTexture->setImage(m_sVideo.pImage.get());
pVideoTexture->setResizeNonPowerOfTwoHint(tFalse);
if (bUseGCL && m_bUseFBO)
{
pVideoTexture->setFilter(osg::Texture::MIN_FILTER, osg::Texture::NEAREST);
}
tInt nWidth = m_sVideo.sFormat.nWidth;
tInt nHeight = m_sVideo.sFormat.nHeight;
osg::Viewport* pViewport = m_pViewer->getCamera()->getViewport();
tInt nVW = pViewport->width();
tInt nVH = pViewport->height();
if (bUseGCL)
{
osg::Texture2D* pCamTex = new osg::Texture2D;
pCamTex->setTextureSize(nWidth, nHeight);
pCamTex->setInternalFormat(GL_RGBA);
m_sVideo.pGCLCam = new osg::Camera;
m_sVideo.pGCLCam->setClearColor(osg::Vec4(0.0, 0.0, 0.0, 1.0));
m_sVideo.pGCLCam->setProjectionMatrixAsOrtho2D(0, nWidth, nHeight, 0);
m_sVideo.pGCLCam->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
m_sVideo.pGCLCam->setViewport(0, 0, nWidth, nHeight);
m_sVideo.pGCLCam->setRenderOrder(osg::Camera::PRE_RENDER);
if (m_bUseFBO)
{
m_sVideo.pGCLCam->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT);
}
m_sVideo.pGCLCam->attach(osg::Camera::COLOR_BUFFER, pCamTex, 0, 0, true);
{
osg::Geode* pVideoGeode = new osg::Geode;
m_sVideo.pGCLCam->addChild(pVideoGeode);
osg::Geometry* pGeom = new osg::Geometry;
pVideoGeode->addDrawable(pGeom);
osg::StateSet* pState = new osg::StateSet;
pState->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
pState->setMode(GL_CULL_FACE, osg::StateAttribute::OFF);
pVideoGeode->setStateSet(pState);
osg::Vec2Array* pCoords = new osg::Vec2Array;
pCoords->push_back(osg::Vec2(0, 0));
pCoords->push_back(osg::Vec2(0, m_sVideo.sFormat.nHeight));
pCoords->push_back(osg::Vec2(m_sVideo.sFormat.nWidth, m_sVideo.sFormat.nHeight));
pCoords->push_back(osg::Vec2(m_sVideo.sFormat.nWidth, 0));
pGeom->setVertexArray(pCoords);
osg::Vec4Array* pColors = new osg::Vec4Array;
pColors->push_back(osg::Vec4d(1.0, 1.0, 1.0, 1.0));
pGeom->setColorArray(pColors, osg::Array::BIND_OVERALL);
pGeom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS, 0, 4));
pState->setTextureAttributeAndModes(0, pVideoTexture, osg::StateAttribute::ON);
osg::Vec2Array* pVidTexCoords = new osg::Vec2Array(4);
tFloat64 fX = m_sVideo.sFormat.nWidth / (tFloat64) nWidth;
tFloat64 fY = m_sVideo.sFormat.nHeight / (tFloat64) nHeight;
(*pVidTexCoords)[1].set(0.0, fY);
(*pVidTexCoords)[0].set(0.0, 0.0);
(*pVidTexCoords)[3].set(fX, 0.0);
(*pVidTexCoords)[2].set(fX, fY);
pGeom->setTexCoordArray(0, pVidTexCoords);
}
{
osg::Geode* pGCLGeode = new osg::Geode;
m_sVideo.pGCLCam->addChild(pGCLGeode);
m_sVideo.pGCL = new cGCLDrawable(m_sVideo.sFormat.nWidth, m_sVideo.sFormat.nHeight);
pGCLGeode->addDrawable(m_sVideo.pGCL.get());
osg::StateSet* pState = new osg::StateSet;
pState->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
pState->setMode(GL_CULL_FACE, osg::StateAttribute::OFF);
pState->setMode(GL_BLEND, osg::StateAttribute::ON);
pState->setAttribute(new osg::Depth(osg::Depth::ALWAYS), osg::StateAttribute::ON);
pGCLGeode->setStateSet(pState);
}
m_sVideo.pTransform->addChild(m_sVideo.pGCLCam.get());
m_sVideo.pVideoState->setTextureAttributeAndModes(0, pCamTex, osg::StateAttribute::ON);
if (m_bUseFBO)
{
UpdateGCLCam(nWidth, nHeight);
}
else
{
UpdateGCLCam(nVW, nVH);
}
}
else
{
m_sVideo.pVideoState->setTextureAttributeAndModes(0, pVideoTexture, osg::StateAttribute::ON);
osg::Vec2Array* pTexCoords = new osg::Vec2Array(4);
tFloat64 fX = m_sVideo.sFormat.nWidth / (tFloat64) nWidth;
tFloat64 fY = m_sVideo.sFormat.nHeight / (tFloat64) nHeight;
(*pTexCoords)[0].set(fX, 0.0);
(*pTexCoords)[1].set(fX, fY);
(*pTexCoords)[2].set(0.0, fY);
(*pTexCoords)[3].set(0.0, 0.0);
m_sVideo.pVideoGeometry->setTexCoordArray(0, pTexCoords);
}
}
ShowVideo(bOldShowVideo);
SetCameraView(bOldCameraView);
RETURN_NOERROR;
}
tResult cVideoViewMixin::ProcessInput(ISampleReader* pReader, const iobject_ptr<const ISample>& pSample)
{
if (m_sVideo.bFormatChanged)
{
RETURN_NOERROR;
}
if (pReader == m_sVideo.pVideoReader && m_sVideo.pImage)
{
sample_data<tUInt8> pImageData(pSample);
auto pSrcBuffer = pImageData.GetDataPtr();
if (m_sVideo.bConvertToRGB)
{
m_sVideo.oConvertImg.Attach(const_cast<tUInt8*>(pSrcBuffer), &m_sVideo.sFormat);
RETURN_IF_FAILED(m_sVideo.oConvertImg.ChangePixelFormat(cImage::PF_RGB_888));
pSrcBuffer = m_sVideo.oConvertImg.GetBitmap();
}
m_sVideo.pImage->setImage(m_sVideo.sFormat.nWidth,
m_sVideo.sFormat.nHeight,
1,
m_sVideo.nBitmapFormatInternal,
m_sVideo.nBitmapFormat,
m_sVideo.nPixelType,
const_cast<tUInt8*>(pSrcBuffer),
osg::Image::NO_DELETE,
4);
m_sVideo.pCurSample = pSample;
}
else if (pReader == m_sVideo.pCalibrationReader)
{
sample_data<tCameraProjection> oProjection(pSample);
Calibrate(oProjection.GetDataPtr());
}
else if (pReader == m_sVideo.pGCLReader)
{
if (!m_sVideo.bUseGCL)
{
m_sVideo.bUseGCL = tTrue;
m_sVideo.bFormatChanged = tTrue;
}
else
{
sample_data<tUInt8> oData(pSample);
m_sVideo.pGCL->UpdateCommands(oData.GetDataPtr(), oData.GetDataSize());
}
}
RETURN_NOERROR;
}
tResult cVideoViewMixin::AddMenuItemForPick(IMenu& oMenu, const tNodePath& sNodePath)
{
RETURN_IF_FAILED(cMixin::AddMenuItemForPick(oMenu, sNodePath));
oMenu.AddSeparator();
auto pVideoMenu = oMenu.AddMenu("Video");
auto pMenuItem = pVideoMenu->AddMenuItem("Show Video");
RETURN_IF_POINTER_NULL(pMenuItem);
pMenuItem->SetCheckable(tTrue);
pMenuItem->SetChecked(m_sVideo.bShowVideo);
pMenuItem->SetEventHandler(this);
if (!m_sVideo.bCameraView)
{
pVideoMenu->AddMenuItem("Camera View")->SetEventHandler(this);
}
RETURN_NOERROR;
}
tResult cVideoViewMixin::AddGlobalMenuItem(IMenu& oMenu)
{
RETURN_IF_FAILED(cMixin::AddGlobalMenuItem(oMenu));
if (m_pOldManip.get())
{
oMenu.AddMenuItem("Reset Camera")->SetEventHandler(this);
}
if (m_sVideo.bShowVideo)
{
oMenu.AddMenuItem("Hide Video")->SetEventHandler(this);
}
else
{
oMenu.AddMenuItem("Show Video")->SetEventHandler(this);
}
if (m_bShowCameraSymbol)
{
oMenu.AddMenuItem("Hide Camera Symbols")->SetEventHandler(this);
}
else
{
oMenu.AddMenuItem("Show Camera Symbols")->SetEventHandler(this);
}
RETURN_NOERROR;
}
#define IF_FORMAT(__stream_type_format, __image_format)\
if (sFormat.m_strFormatName == __stream_type_format::FormatName)\
{\
sBitmapFormat.nPixelFormat = __image_format;\
}
#define ELSE_IF_FORMAT(__stream_type_format, __image_format) else IF_FORMAT(__stream_type_format, __image_format)
tBitmapFormat get_bitmap_format_from_image_format(
const tStreamImageFormat& sFormat)
{
sBitmapFormat.
nSize = sFormat.m_szMaxByteSize;
sBitmapFormat.
nWidth = sFormat.m_ui32Width;
sBitmapFormat.
nHeight = sFormat.m_ui32Height;
sBitmapFormat.
nBitsPerPixel = stream_image_format_get_generic_pixel_size(sFormat);
IF_FORMAT(stream_image_format::GREYSCALE_8, IImage::PF_GREYSCALE_8)
ELSE_IF_FORMAT(stream_image_format::GREYSCALE_16, IImage::PF_GREYSCALE_16)
ELSE_IF_FORMAT(stream_image_format::GREYSCALE_24, IImage::PF_GREYSCALE_24)
ELSE_IF_FORMAT(stream_image_format::GREYSCALE_32, IImage::PF_GREYSCALE_32)
ELSE_IF_FORMAT(stream_image_format::RGB_8, IImage::PF_RGB_8)
ELSE_IF_FORMAT(stream_image_format::RGB_24, IImage::PF_RGB_888)
ELSE_IF_FORMAT(stream_image_format::RGB_32, IImage::PF_RGBA_8888)
ELSE_IF_FORMAT(stream_image_format::RGB_555, IImage::PF_RGB_555)
ELSE_IF_FORMAT(stream_image_format::RGB_565, IImage::PF_RGB_565)
ELSE_IF_FORMAT(stream_image_format::BGR_24, IImage::PF_BGR_888)
ELSE_IF_FORMAT(stream_image_format::BGR_32, IImage::PF_BGRA_8888)
ELSE_IF_FORMAT(stream_image_format::ABGR_32, IImage::PF_ABGR_8888)
ELSE_IF_FORMAT(stream_image_format::ARGB_32, IImage::PF_ARGB_8888)
ELSE_IF_FORMAT(stream_image_format::BGRA_32, IImage::PF_BGRA_8888)
ELSE_IF_FORMAT(stream_image_format::RGBA_32, IImage::PF_RGBA_8888)
ELSE_IF_FORMAT(stream_image_format::YUV420P, IImage::PF_YUV420P_888)
return sBitmapFormat;
}
tResult cVideoViewMixin::AcceptType(ISampleReader* pReader, const iobject_ptr<const IStreamType>& pType)
{
RETURN_IF_FAILED(cMixin::AcceptType(pReader, pType));
if (pReader == m_sVideo.pVideoReader)
{
tStreamImageFormat sFormat;
RETURN_IF_FAILED(adtf::streaming::get_stream_type_image_format(sFormat, *pType.Get()));
if (sFormat == tStreamImageFormat())
{
RETURN_ERROR_DESC(ERR_INVALID_TYPE, "Default image format is not accepted. Waiting for full image format.");
}
m_sVideo.sFormat = get_bitmap_format_from_image_format(sFormat);
m_sVideo.bFormatChanged = tTrue;
}
RETURN_NOERROR;
}
tResult cVideoViewMixin::HandleMenuEvent(const tChar* strMenuText, tVoid* )
{
std::string strHelper(strMenuText);
m_pIViewer->Lock();
if (strHelper == "Camera View")
{
SetCameraView(tTrue);
}
else if (strHelper == "Reset Camera")
{
SetCameraView(tFalse);
}
else if (strHelper == "Hide Camera Symbols")
{
m_bShowCameraSymbol = tFalse;
m_sVideo.pTransform->removeChild(m_sVideo.pCam.get());
}
else if (strHelper == "Show Camera Symbols")
{
m_bShowCameraSymbol = tTrue;
m_sVideo.pTransform->addChild(m_sVideo.pCam.get());
}
else if (strHelper == "Hide Video")
{
ShowVideo(tFalse);
}
else if (strHelper == "Show Video")
{
ShowVideo(tTrue);
}
m_pIViewer->Unlock();
RETURN_NOERROR;
}
tResult cVideoViewMixin::SetUpCamera()
{
tFloat64 fZNear = 1.0;
tFloat64 fZFar = m_fFarClipping;
if (!m_bKeepAspect)
{
tFloat fQ = fZFar / (fZFar -fZNear);
osg::Matrixd oMatrix;
tFloat64* pMat = oMatrix.ptr();
pMat[0] = 2.0 * m_sVideo.oCamera.m_fFocalX / m_sVideo.oCamera.m_nResX;
pMat[1] = 0.0;
pMat[2] = 0.0;
pMat[3] = 0.0;
pMat[4] = 0.0;
pMat[5] = 2.0 * m_sVideo.oCamera.m_fFocalY / m_sVideo.oCamera.m_nResY;
pMat[6] = 0.0;
pMat[7] = 0.0;
pMat[8] = -2.0 * ((tFloat64) (m_sVideo.oCamera.m_fPrincipalX) / (m_sVideo.oCamera.m_nResX) - 0.5);
pMat[9] = 2.0 * ((tFloat64) m_sVideo.oCamera.m_fPrincipalY / (m_sVideo.oCamera.m_nResY) - 0.5);
pMat[10] = fQ;
pMat[11] = -1.0;
pMat[12] = 0.0;
pMat[13] = 0.0;
pMat[14] = -fQ * fZNear;
pMat[15] = 0.0;
m_pViewer->getCamera()->setProjectionMatrix(oMatrix);
}
else
{
osg::Viewport* pViewport = m_pViewer->getCamera()->getViewport();
tFloat64 fAspect = pViewport->width() / pViewport->height();
tFloat fQ = fZFar / (fZFar -fZNear);
osg::Matrixd oMatrix;
tFloat64* pMat = oMatrix.ptr();
pMat[0] = 2.0 * m_sVideo.oCamera.m_fFocalX / (m_sVideo.oCamera.m_nResY * fAspect);
pMat[1] = 0.0;
pMat[2] = 0.0;
pMat[3] = 0.0;
pMat[4] = 0.0;
pMat[5] = 2.0 * m_sVideo.oCamera.m_fFocalY / m_sVideo.oCamera.m_nResY;
pMat[6] = 0.0;
pMat[7] = 0.0;
pMat[8] = -2.0 * ((tFloat64) (m_sVideo.oCamera.m_fPrincipalX) / (m_sVideo.oCamera.m_nResX) - 0.5);
pMat[9] = 2.0 * ((tFloat64) m_sVideo.oCamera.m_fPrincipalY / (m_sVideo.oCamera.m_nResY) - 0.5);
pMat[10] = fQ;
pMat[11] = -1.0;
pMat[12] = 0.0;
pMat[13] = 0.0;
pMat[14] = -fQ * fZNear;
pMat[15] = 0.0;
m_pViewer->getCamera()->setProjectionMatrix(oMatrix);
}
m_sVideo.bCameraView = tTrue;
RETURN_NOERROR;
}
tResult cVideoViewMixin::Calibrate(const tCameraProjection* pCalib)
{
m_sVideo.oCamera.m_fFocalX = pCalib->f32FocalX;
m_sVideo.oCamera.m_fFocalY = pCalib->f32FocalY;
m_sVideo.oCamera.m_fPosX = pCalib->f32PosX;
m_sVideo.oCamera.m_fPosY = pCalib->f32PosY;
m_sVideo.oCamera.m_fPosZ = pCalib->f32PosZ;
m_sVideo.oCamera.m_fPrincipalX = pCalib->f32PrincipalX;
m_sVideo.oCamera.m_fPrincipalY = pCalib->f32PrincipalY;
m_sVideo.oCamera.m_fRotX = pCalib->f32RotX;
m_sVideo.oCamera.m_fRotY = pCalib->f32RotY;
m_sVideo.oCamera.m_fRotZ = pCalib->f32RotZ;
m_sVideo.oCamera.m_nResX = m_sVideo.sFormat.nWidth;
m_sVideo.oCamera.m_nResY = m_sVideo.sFormat.nHeight;
UpdateCamAndScreen();
if (m_sVideo.bCameraView)
{
SetUpCamera();
}
RETURN_NOERROR;
}
tResult cVideoViewMixin::UpdateCamAndScreen()
{
tFloat64 fScreenDist = m_sVideo.bCameraView ? m_fFarClipping * 0.95 : m_sVideo.fScreenDist;
m_sVideo.vPosition.x() = m_sVideo.oCamera.m_fPosX;
m_sVideo.vPosition.y() = m_sVideo.oCamera.m_fPosY;
m_sVideo.vPosition.z() = m_sVideo.oCamera.m_fPosZ;
m_sVideo.pTransform->setPosition(m_sVideo.vPosition);
m_sVideo.pTransform->setAttitude(osg::Quat(m_sVideo.oCamera.m_fRotX, osg::Vec3(1, 0, 0),
m_sVideo.oCamera.m_fRotZ, osg::Vec3(0, 0, 1),
m_sVideo.oCamera.m_fRotY, osg::Vec3(0, 1, 0)));
tFloat64 fDown = m_sVideo.oCamera.m_nResY - m_sVideo.oCamera.m_fPrincipalY;
tFloat64 fUp = m_sVideo.oCamera.m_nResY - fDown;
tFloat64 fUpV = fUp / m_sVideo.oCamera.m_fFocalY;
tFloat64 fDownV = fDown / m_sVideo.oCamera.m_fFocalY;
tFloat64 fRight = m_sVideo.oCamera.m_nResX - m_sVideo.oCamera.m_fPrincipalX;
tFloat64 fLeft = m_sVideo.oCamera.m_nResX - fRight;
tFloat64 fRightV = fRight / m_sVideo.oCamera.m_fFocalX;
tFloat64 fLeftV = fLeft / m_sVideo.oCamera.m_fFocalX;
osg::Vec3Array* pCoords = new osg::Vec3Array;
pCoords->push_back(osg::Vec3(fScreenDist,
fScreenDist * -fRightV,
fScreenDist * fUpV));
pCoords->push_back(osg::Vec3(fScreenDist,
fScreenDist * -fRightV,
fScreenDist * -fDownV));
pCoords->push_back(osg::Vec3(fScreenDist,
fScreenDist * fLeftV,
fScreenDist * -fDownV));
pCoords->push_back(osg::Vec3(fScreenDist,
fScreenDist * fLeftV,
fScreenDist * fUpV));
m_sVideo.pVideoGeometry->setVertexArray(pCoords);
m_sVideo.pVideoGeometry->dirtyDisplayList();
RETURN_NOERROR;
}
bool cVideoViewMixin::handle(const osgGA::GUIEventAdapter & ea, osgGA::GUIActionAdapter & , osg::Object *, osg::NodeVisitor *)
{
if (ea.getEventType() & osgGA::GUIEventAdapter::KEYDOWN)
{
m_pIViewer->Lock();
tBool bSetup = tTrue;
switch (ea.getKey())
{
case 'p' :
{
SetCameraView(tTrue);
}
break;
default:
bSetup = tFalse;
break;
}
if (bSetup)
{
UpdateCamAndScreen();
SetUpCamera();
}
m_pIViewer->Unlock();
}
if (ea.getEventType() & osgGA::GUIEventAdapter::RESIZE)
{
if (m_sVideo.pGCLCam.get())
{
UpdateGCLCam(ea.getWindowWidth(), ea.getWindowHeight());
}
}
return false;
}
tResult cVideoViewMixin::UpdateGCLCam(tInt nVW, tInt nVH)
{
tInt nWidth = m_sVideo.sFormat.nWidth;
tInt nHeight = m_sVideo.sFormat.nHeight;
osg::Matrixd oVMatrix;
if (nVW < nWidth && m_sVideo.sFormat.nWidth > nVW)
{
oVMatrix(0,0) = nVW / (tFloat64) m_sVideo.sFormat.nWidth;
}
if (nVH < nHeight && m_sVideo.sFormat.nHeight > nVH)
{
oVMatrix(1,1) = nVH / (tFloat64) m_sVideo.sFormat.nHeight;
}
oVMatrix(3,1) = nHeight - MIN(nVH, m_sVideo.sFormat.nHeight) < 0 ? 0 : nHeight - MIN(nVH, m_sVideo.sFormat.nHeight);
m_sVideo.pGCLCam->setViewMatrix(oVMatrix);
osg::Vec2Array* pTexCoords = new osg::Vec2Array(4);
tFloat64 fX = MIN(nVW, m_sVideo.sFormat.nWidth) / (tFloat64) nWidth;
tFloat64 fY = MIN(nVH, m_sVideo.sFormat.nHeight) / (tFloat64) nHeight;
(*pTexCoords)[0].set(fX, fY);
(*pTexCoords)[1].set(fX, 0.0);
(*pTexCoords)[2].set(0.0, 0.0);
(*pTexCoords)[3].set(0.0, fY);
m_sVideo.pVideoGeometry->setTexCoordArray(0, pTexCoords);
RETURN_NOERROR;
}
tResult cVideoViewMixin::ShowVideo(tBool bShow)
{
if (bShow == m_sVideo.bShowVideo)
{
RETURN_NOERROR;
}
if (!bShow)
{
m_sVideo.pTransform->removeChild(m_sVideo.pVideo.get());
m_sVideo.pTransform->removeChild(m_sVideo.pGCLCam.get());
}
else
{
if (m_sVideo.pGCLCam.get())
{
m_sVideo.pTransform->addChild(m_sVideo.pGCLCam.get());
}
m_sVideo.pTransform->addChild(m_sVideo.pVideo.get());
}
m_sVideo.bShowVideo = bShow;
RETURN_NOERROR;
}
tResult cVideoViewMixin::SetCameraView(tBool bCameraView)
{
if (bCameraView == m_sVideo.bCameraView)
{
RETURN_NOERROR;
}
m_sVideo.bCameraView = bCameraView;
if (!bCameraView)
{
if (m_pOldManip.get())
{
m_pViewer->getCamera()->setProjectionMatrix(m_oOldProjectionMatrix);
if (m_bShowCameraSymbol)
{
m_sVideo.pTransform->addChild(m_sVideo.pCam.get());
}
m_pViewer->setCameraManipulator(m_pOldManip.get());
m_pOldManip.release();
}
}
else
{
if (!m_pOldManip.get())
{
m_pOldManip = m_pViewer->getCameraManipulator();
m_oOldProjectionMatrix = m_pViewer->getCamera()->getProjectionMatrix();
auto pTracker = new cCameraManipulator;
pTracker->setTrackNode(m_sVideo.pTransform->getChild(0));
m_pViewer->setCameraManipulator(pTracker);
}
m_sVideo.pTransform->removeChild(m_sVideo.pCam.get());
SetUpCamera();
}
RETURN_NOERROR;
}
void cExtDrawCallback::operator () (osg::RenderInfo& renderInfo) const
{
if (m_pMixin->m_sVideo.bFormatChanged)
{
m_pMixin->CreateVideoWall();
}
if (m_pPrevious)
{
(*m_pPrevious)(renderInfo);
}
}