Files
CodeRepository/Common/OpenGLView.cpp

602 lines
14 KiB
C++
Raw Normal View History

#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;
}