#include "OpenGLView.h" #include #include #include "CommSerialDef.h" #include "CommDef.h" CTexture::CTexture() { m_nTextureNum = 0; m_nCurrentTextureIndex = 0; m_bInit = false; m_bGenTextureData = false; for(int i = 0; i < MAX_TEXTURES; i++) { m_nTextures[i] = -1; } } CTexture::~CTexture() { Unint(); } void CTexture::Init(int nTextureNum) { Unint(); m_nTextureNum = (nTextureNum > MAX_TEXTURES) ? MAX_TEXTURES : nTextureNum; m_nTextureNum = (nTextureNum < 1) ? 1 : nTextureNum; glGenTextures(m_nTextureNum, &m_nTextures[0]); m_bInit = true; } void CTexture::Unint() { if(m_bInit) { // 删除所有的纹理 glDeleteTextures(m_nTextureNum, &m_nTextures[0]); for(int i = 0; i < MAX_TEXTURES; i++) { m_nTextures[i] = -1; } m_nTextureNum = 0; m_bInit = false; m_bGenTextureData = false; } } bool CTexture::GenTextureData(int nTextureIndex, int nTextureWidth, int nTextureHeight, int nDataWidth) { if(!m_bInit) { return false; } if(nTextureIndex < 0 || nTextureIndex >= m_nTextureNum) { return false; } m_nCurrentTextureIndex = nTextureIndex; int nTextureComposite = 0; int nBytesOfPixel = nDataWidth / 8; switch (nBytesOfPixel) { case 1: { nTextureComposite = GL_LUMINANCE; break; } case 3: { nTextureComposite = GL_RGB; break; } case 4: { nTextureComposite = GL_RGBA; break; } default: { nTextureComposite = GL_RGBA; break; } } unsigned char* pTextureData = new unsigned char[nTextureWidth * nTextureHeight * nBytesOfPixel]; memset(pTextureData, 128, nTextureWidth * nTextureHeight * nBytesOfPixel); glBindTexture(GL_TEXTURE_2D, m_nTextures[m_nCurrentTextureIndex]); glTexImage2D(GL_TEXTURE_2D, 0, nTextureComposite, nTextureWidth, nTextureHeight, 0, nTextureComposite, GL_UNSIGNED_BYTE, pTextureData); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); delete [] pTextureData; pTextureData = nullptr; m_bGenTextureData = true; return true; } //bmp图片默认RGBA bool CTexture::UpdataTextureGray(int nTextureIndex, char* pTextureData, int nTextureWidth, int nTextureHeight) { if(nTextureIndex < 0 || nTextureIndex >= m_nTextureNum) { return false; } m_nCurrentTextureIndex = nTextureIndex; glBindTexture(GL_TEXTURE_2D, m_nTextures[nTextureIndex]); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, nTextureWidth, nTextureHeight, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, pTextureData); return true; } bool CTexture::UpdataTexture(int nTextureIndex, char* pTextureData, int nTextureWidth, int nTextureHeight) { if(nTextureIndex < 0 || nTextureIndex >= m_nTextureNum) { return false; } m_nCurrentTextureIndex = nTextureIndex; glBindTexture(GL_TEXTURE_2D, m_nTextures[nTextureIndex]); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, nTextureWidth, nTextureHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, pTextureData); return true; } GLuint CTexture::CurrentTexture() { if(!m_bInit) { return -1; } if(!m_bGenTextureData) { return -1; } return m_nTextures[m_nCurrentTextureIndex]; } OpenGLView::OpenGLView(QWidget *parent, int iID, Qt::WindowFlags f) { setWindowFlags(Qt::CustomizeWindowHint|Qt::FramelessWindowHint); this->setParent(parent); m_parentWidget = parent; OnMouseCallback = nullptr; m_nXPos = 0; m_nYPos = 0; m_dRatio = 1; m_pPBOBuffer[0] = nullptr; m_pPBOBuffer[1] = nullptr; m_nPBO_Now = 0; m_nPBO_Next = 0; m_pImageDataBuffer = nullptr; m_bInit = false; m_nImageWidth = 0; m_nImageHeight = 0; m_nImageDataSize = 0; m_bInitedGLRes = false; m_nRefreshCount = 0; m_eViewOrder = eViewOrder_Origin; } OpenGLView::~OpenGLView() { UninitGLRes(); Uninit(); m_varTimer.stop(); disconnect(&m_varTimer, &QTimer::timeout, this, &OpenGLView::OnTimer_Update); delete[] m_pImageDataBuffer; m_pImageDataBuffer = nullptr; m_bInit = false; for (int i = 0; i < 2; i++) { //1 if (m_pPBOBuffer[i]) { m_pPBOBuffer[i]->release(); } } } bool OpenGLView::Init(int nImageWidth, int nImageHeight) { Uninit(); // m_bInitedGLRes = false; // m_nImageWidth = nImageWidth; m_nImageHeight = nImageHeight; m_nImageDataSize = m_nImageWidth * m_nImageHeight * 4; m_varImageData.InitQueue(m_nImageDataSize, 2); // m_pImageDataBuffer = new byte[m_nImageWidth * m_nImageHeight * 4]; memset(m_pImageDataBuffer, 108, m_nImageWidth * m_nImageHeight * 4); if(nullptr == m_pImageDataBuffer) { return false; } for (int h = 0; h < m_nImageHeight; h++) { memset(m_pImageDataBuffer + h*m_nImageWidth*4, h, m_nImageWidth*4); } // connect(&m_varTimer, &QTimer::timeout, this, &OpenGLView::OnTimer_Update); connect(&m_varTimer, &QTimer::timeout, this, &OpenGLView::OnTimer_InitGLRes); m_varTimer.setTimerType(Qt::PreciseTimer); m_varTimer.start(5); // m_bInit = true; // m_nRefreshCount = 2; return true; } void OpenGLView::Uninit() { if(m_bInit) { disconnect(&m_varTimer, &QTimer::timeout, this, &OpenGLView::OnTimer_Update); m_varTimer.stop(); if(nullptr != m_pImageDataBuffer) { delete [] m_pImageDataBuffer; m_pImageDataBuffer = nullptr; } m_bInit = false; } } bool OpenGLView::InitGLRes() { UninitGLRes(); if(!m_bInit) { return false; } // m_varTexture.Init(1); m_varTexture.GenTextureData(0, m_nImageWidth, m_nImageHeight, 32); // RGBA纹理 // for (int i = 0; i < 2; i++) { //1 m_pPBOBuffer[i] = new QOpenGLBuffer(QOpenGLBuffer::PixelUnpackBuffer); m_pPBOBuffer[i]->create(); m_pPBOBuffer[i]->allocate(m_nImageDataSize); m_pPBOBuffer[i]->bind(); } initializeGLFunctions(); glClearColor(0, 0, 255, 255); return true; } void OpenGLView::UninitGLRes() { // for (int i = 0; i < 2; i++) { if(nullptr != m_pPBOBuffer[i]) { m_pPBOBuffer[i]->release(); m_pPBOBuffer[i]->destroy(); delete m_pPBOBuffer[i]; m_pPBOBuffer[i] = nullptr; } } } void OpenGLView::UpdateImageData(byte* pImageData, bool bTryFresh) { if(!m_bInit || !m_bInitedGLRes) { return; } int nRes = 0; m_varImageData.PushBack(pImageData, m_nImageDataSize, nRes); if(bTryFresh) { m_nRefreshCount = 2; } } void OpenGLView::initializeGL() { m_bInitedGLRes = true; InitGLRes(); } //窗口大小响应函数,在创建窗口时系统会自动调用 void OpenGLView::resizeGL(int nViewWidth, int nViewHeight) { if(!m_bInit) { return; } //按比例绘制 int iX = 0, iY = 0; //窗口中显示视图的左上角坐标 GLdouble Ratio_W = GLdouble(nViewWidth)/m_nImageWidth; GLdouble Ratio_H = GLdouble(nViewHeight)/m_nImageHeight; GLdouble Ratio = Ratio_WRatio_H) { iX = (nViewWidth-m_nImageWidth*Ratio)/2; iY = 0; } glViewport(iX, iY, m_nImageWidth*Ratio, m_nImageHeight*Ratio+1); m_nXPos = iX; m_nYPos = iY; m_dRatio = Ratio; glMatrixMode(GL_PROJECTION); glLoadIdentity(); m_fScreenWid = GLfloat(nViewWidth) / nViewHeight; glFrustum(-m_fScreenWid, m_fScreenWid, -1.0, 1.0, 8.0, 100.0); glMatrixMode(GL_MODELVIEW); } void OpenGLView::paintGL() { draw(); } void OpenGLView::draw() { if(!m_bInit) { return; } if(!m_bInitedGLRes) { return; } glClearColor(0.0f,0.0f,0.0f,1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glPushMatrix(); glTranslatef(0.0, 0.0 + 1.0, -8.0);//0.5 + moveY glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, m_varTexture.CurrentTexture()); const bool c_bPboMode = true; if(c_bPboMode) { m_nPBO_Now = (m_nPBO_Now + 1) % 2; m_nPBO_Next = (m_nPBO_Now + 1) % 2; m_pPBOBuffer[m_nPBO_Now]->bind(); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_nImageWidth, m_nImageHeight, GL_RGBA, GL_UNSIGNED_BYTE, 0); //..CPU导入数据采用的是DMA模式;从CPU将最新图像数据导入GPU贴图缓冲区 m_pPBOBuffer[m_nPBO_Next]->bind(); glBufferData(GL_PIXEL_UNPACK_BUFFER, m_nImageDataSize, 0, GL_STREAM_DRAW); void* pGpuMem = m_pPBOBuffer[m_nPBO_Next]->map(QOpenGLBuffer::WriteOnly); if(nullptr != pGpuMem) { memcpy(pGpuMem, m_pImageDataBuffer, m_nImageDataSize); } m_pPBOBuffer[m_nPBO_Next]->unmap(); } else//CPU导入数据,使用CPU拷贝模式;占用CPU的运算资源 { // textr->UpdataTexture(iTexA[0], (char *)m_byTemp, DefaultImageWidth, DefaultImageHeight * m_iImageNum);//iTexA[0]//m_iTextureID } glColor3f(1.0,1.0,1.0); // 设置颜色 glShadeModel(GL_SMOOTH); // 设置平滑 glDepthMask(GL_FALSE); // 关闭深度 glBegin(GL_TRIANGLE_STRIP); // 三角片序列绘制 switch (m_eViewOrder) { case eViewOrder_Origin: { glTexCoord2f(0.0f, 0.0f); // 第一个点纹理坐标设置 glVertex3f(-m_fScreenWid, 0.0f, 0.0f); // 第一个点三维坐标设置 glTexCoord2f(0.0f, 1.0f); // 第二个点纹理坐标设置 glVertex3f(-m_fScreenWid, -2.0f, 0.0f); // 第二个点三维坐标设置 glTexCoord2f(1.0f, 0.0f); // 第三个点纹理坐标设置 glVertex3f(m_fScreenWid, 0.0f, 0.0f); // 第三个点三维坐标设置 glTexCoord2f(1.0f, 1.0f); // 第四个点纹理坐标设置 glVertex3f(m_fScreenWid, -2.0f, 0.0f); // 第四个点三维坐标设置 break; } case eViewOrder_LeftRightRevert: { glTexCoord2f(0.0f, 0.0f); glVertex3f(m_fScreenWid, 0.0f, 0.0f); glTexCoord2f(0.0f, 1.0f); glVertex3f(m_fScreenWid, -2.0f, 0.0f); glTexCoord2f(1.0f, 0.0f); glVertex3f(-m_fScreenWid, 0.0f, 0.0f); glTexCoord2f(1.0f, 1.0f); glVertex3f(-m_fScreenWid, -2.0f, 0.0f); break; } case eViewOrder_UpDownRevert: { glTexCoord2f(0.0f, 0.0f); glVertex3f(-m_fScreenWid, -2.0f, 0.0f); glTexCoord2f(0.0f, 1.0f); glVertex3f(-m_fScreenWid, 0.0f, 0.0f); glTexCoord2f(1.0f, 0.0f); glVertex3f(m_fScreenWid, -2.0f, 0.0f); glTexCoord2f(1.0f, 1.0f); glVertex3f(m_fScreenWid, 0.0f, 0.0f); break; } case eViewOrder_AllRevert: { glTexCoord2f(0.0f, 0.0f); glVertex3f(m_fScreenWid, -2.0f, 0.0f); glTexCoord2f(0.0f, 1.0f); glVertex3f(m_fScreenWid, 0.0f, 0.0f); glTexCoord2f(1.0f, 0.0f); glVertex3f(-m_fScreenWid, -2.0f, 0.0f); glTexCoord2f(1.0f, 1.0f); glVertex3f(-m_fScreenWid, 0.0f, 0.0f); break; } default: // origin { glTexCoord2f(0.0f, 0.0f); // 第一个点纹理坐标设置 glVertex3f(-m_fScreenWid, 0.0f, 0.0f); // 第一个点三维坐标设置 glTexCoord2f(0.0f, 1.0f); // 第二个点纹理坐标设置 glVertex3f(-m_fScreenWid, -2.0f, 0.0f); // 第二个点三维坐标设置 glTexCoord2f(1.0f, 0.0f); // 第三个点纹理坐标设置 glVertex3f(m_fScreenWid, 0.0f, 0.0f); // 第三个点三维坐标设置 glTexCoord2f(1.0f, 1.0f); // 第四个点纹理坐标设置 glVertex3f(m_fScreenWid, -2.0f, 0.0f); // 第四个点三维坐标设置 break; } } glEnd(); // 三角片序列绘制结束 glDisable(GL_TEXTURE_2D); // 不使能纹理 glDepthMask(GL_TRUE); // 使能深度 glPopMatrix(); // 弹栈 } void OpenGLView::OnTimer_Update() { if(!m_bInit) { return; } if(!m_bInitedGLRes) { return; } // if(m_nRefreshCount > 0) { m_nRefreshCount--; this->updateGL(); } // int nFrameSize = 0; if(!m_varImageData.GetFront(m_pImageDataBuffer, nFrameSize) ) { return; } this->updateGL(); } void OpenGLView::OnTimer_InitGLRes() { if(!m_bInitedGLRes) { InitGLRes(); m_bInitedGLRes = true; } } bool OpenGLView::event(QEvent* event) { if (m_parentWidget && OnMouseCallback) { if(event->type() == QEvent::Leave || event->type() == QEvent::Enter || event->type() == QEvent::MouseButtonPress || event->type() == QEvent::MouseMove || event->type() == QEvent::MouseButtonRelease || event->type() == QEvent::MouseButtonDblClick || event->type() == QEvent::Enter || event->type() == QEvent::Leave ) { //OnMouseCallback(m_iID, event, m_parentWidget); } } return QWidget::event(event); } void OpenGLView::SetCallbackFunc(MouseEventCallback callback) { OnMouseCallback = callback; } void OpenGLView::SetViewOrder(eViewOrder viewOrder) { m_eViewOrder = viewOrder; }