Files
CodeRepository/Common/OpenGLView.cpp
chenzhen 222dda1e43 1,新增“App_ThermalImageSystem”;
2,新增“Apps”;
3,新增“Common”;
4,新增“FileList”;
5,新增“MediaX”;
6,新增“OpenSource”;
7,新增“Samples”;
8,新增“SoftwareBusinessLines”.
2026-02-14 23:03:23 +08:00

602 lines
14 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include "OpenGLView.h"
#include <QTimer>
#include <QMouseEvent>
#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_W<Ratio_H?Ratio_W:Ratio_H;
if(Ratio_W<=Ratio_H)
{
iX = 0;
iY = (nViewHeight-m_nImageHeight*Ratio)/2;
}
else if(Ratio_W>Ratio_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;
}