【发布时间】:2014-05-26 00:15:12
【问题描述】:
我在一个可视化 C++ 应用程序中实现了一个线程,该线程在 OpenGL 窗口中绘制了一系列与立方体矢量相关的立方体,这些立方体具有我所拥有的中心、侧面和水平。它是这个类对象的一个向量,就像一棵树,有不同的层次和层次。在主细化过程中,此对象中的立方体会发生变化:添加、删除...在细化的每一步...
只有在每一步完成后,我才需要重绘(刷新)OpenGL 窗口的内容,以获得该立方体列表演变的动态表示。
我的意思是:
- 第一步完成,我将数组传递给 OpenGL 线程,进行绘制。
- 第二步运行,OpenGL 窗口内容保留第一个立方体。
- 第二步完成,OpenGL 的内容已更新为新的立方体。
- 等等……
它在后台模式线程中的 OpenGL 线程...我只需要在进行详细说明时查看多维数据集的演变...现在,问题在于语句 glutMainLoop() 的情况是连续的.. .而且它太重或崩溃,即使是带有 Nvidia Quadro 4000 的系统....OpenGL 窗口显示,但被阻止、无法移动,有时是灰色或不显示任何内容。
这是我的一段代码(所有与 OpenGL 相关的):
#include <iostream>
#include <opencv\cv.h>
#include <opencv\highgui.h>
#include <opencv2\highgui\highgui.hpp>
#include <windows.h>
#include <process.h>
#include <queue>
#include <array>
#include <vector>
#include <GL/glut.h>
#include <GL/freeglut.h>
using namespace std;
using namespace cv;
//Premessa delle funzioni di posizionamento con mouse
void mouseCB(int button, int stat, int x, int y);
void mouseMotionCB(int x, int y);
//funzioni di inizializzazione e pulizia
bool initSharedMem();
void clearSharedMem();
void initLights();
void setCamera(float posX, float posY, float posZ, float targetX, float targetY, float targetZ);
void toOrtho();
void toPerspective();
//variabili e costanti
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;
const float CAMERA_DISTANCE = 10.0f;
int screenWidth;
int screenHeight;
bool mouseLeftDown;
bool mouseRightDown;
bool mouseMiddleDown;
float mouseX, mouseY;
float cameraAngleX;
float cameraAngleY;
float cameraDistance;
int drawMode;
///////////////////////////////////////////////////////////////////////////////
// Funzione inizializzazione OpenGL standard
///////////////////////////////////////////////////////////////////////////////
void init()
{
glShadeModel(GL_SMOOTH);
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST);
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING);
glEnable(GL_TEXTURE_2D);
glEnable(GL_CULL_FACE);
glEnable(GL_COLOR_MATERIAL);
initLights();
}
///////////////////////////////////////////////////////////////////////////////
// Funzione di inizializzazione globale delle variabili
///////////////////////////////////////////////////////////////////////////////
bool initSharedMem()
{
screenWidth = SCREEN_WIDTH;
screenHeight = SCREEN_HEIGHT;
mouseLeftDown = mouseRightDown = mouseMiddleDown = false;
mouseX = mouseY = 0;
cameraAngleX = cameraAngleY = 0.0f;
//cameraDistance = CAMERA_DISTANCE;
cameraDistance = 0.3f;
drawMode = 0; // 0:pieno, 1: solo contorni, 2:punti
return true;
}
///////////////////////////////////////////////////////////////////////////////
// Funzione di pulitura variabili globali
///////////////////////////////////////////////////////////////////////////////
void clearSharedMem()
{
}
///////////////////////////////////////////////////////////////////////////////
// Inizializzazione Luci
///////////////////////////////////////////////////////////////////////////////
void initLights()
{
GLfloat lightKa[] = {.2f, .2f, .2f, 1.0f}; // luce ambientale
GLfloat lightKd[] = {.7f, .7f, .7f, 1.0f}; // luce diffusa
GLfloat lightKs[] = {1, 1, 1, 1}; // luce speculare
glLightfv(GL_LIGHT0, GL_AMBIENT, lightKa);
glLightfv(GL_LIGHT0, GL_DIFFUSE, lightKd);
glLightfv(GL_LIGHT0, GL_SPECULAR, lightKs);
// posizione delle luci
float lightPos[4] = {0, 0, 20, 1};
glLightfv(GL_LIGHT0, GL_POSITION, lightPos);
//Attiva tutti i settaggi delle luci
glEnable(GL_LIGHT0); }
///////////////////////////////////////////////////////////////////////////////
// Posizione della telecamera e direzioni
///////////////////////////////////////////////////////////////////////////////
void setCamera(float posX, float posY, float posZ, float targetX, float targetY, float targetZ)
{
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(posX, posY, posZ, targetX, targetY, targetZ, 0, 1, 0); // eye(x,y,z), focal(x,y,z), up(x,y,z)
}
///////////////////////////////////////////////////////////////////////////////
// Impostazione proiezione ortogonale
///////////////////////////////////////////////////////////////////////////////
void toOrtho()
{
// Imposta il viewport di tutta la finestra
glViewport(0, 0, (GLsizei)screenWidth, (GLsizei)screenHeight);
// Imposta il frustum di visione
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, screenWidth, 0, screenHeight, -1, 1);
// passaggio a modelview per interattività
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
///////////////////////////////////////////////////////////////////////////////
// Impostazione come perspective
///////////////////////////////////////////////////////////////////////////////
void toPerspective()
{
// Imposta il viewport di tutta la finestra
glViewport(0, 0, (GLsizei)screenWidth, (GLsizei)screenHeight);
//frustum perspective
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
//gluPerspective(60.0f, (float)(screenWidth)/screenHeight, 1.0f, 1000.0f);
gluPerspective(60.0f, (float)(screenWidth)/screenHeight, 10.0f, 0.0f); // FOV, AspectRatio, NearClip, FarClip
// switch to modelview matrix in order to set scene
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
///////////////////////////////////////////////////////////////////////////////
// Funzione ricorsiva di disegno
///////////////////////////////////////////////////////////////////////////////
void addraw(cubo temp)
{
//se non ci sono sottocubi
if (temp.lista_sottocubi.size() == 0)
{
if (temp.livello == LMAXI) {
double centro[3]={(temp.V[6].x)/2, (temp.V[6].y)/2, (temp.V[6].z)/2};
glPushMatrix();
glTranslatef(centro[0],centro[1],centro[2]);
glColor3ub(0,0,255);
glutSolidCube(temp.lato);
glPopMatrix();
}
}
//se i sottocubi ci sono
else {
for (int i=0;i<(int)temp.lista_sottocubi.size();i++){
addraw(temp.lista_sottocubi[i]);
}
}
}
///////////////////////////////////////////////////////////////////////////////
// Funzione disegno principale
///////////////////////////////////////////////////////////////////////////////
void draw()
{
// clear buffer
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
glPushMatrix();
//spostamento del disegno
glTranslatef(0, 0, -cameraDistance);
glRotatef(cameraAngleX, 1, 0, 0); // pitch
glRotatef(cameraAngleY, 0, 1, 0); // heading
//lancio funzione di disegno vera e propria
addraw(prova);
//reset
glPopMatrix();
glutSwapBuffers();
}
//////////////////////////////////////////////////////////////////////////////
// Funzione di reshape
///////////////////////////////////////////////////////////////////////////////
void reshape(int w, int h)
{
screenWidth = w;
screenHeight = h;
toPerspective();
}
///////////////////////////////////////////////////////////////////////////////
// Funzione di refresh temporizzato della finestra
///////////////////////////////////////////////////////////////////////////////
void timerCB(int millisec){
glutTimerFunc(millisec, timerCB, millisec);
glutPostRedisplay();
}
///////////////////////////////////////////////////////////////////////////////
// Funzione rilevamento movimenti del mouse
///////////////////////////////////////////////////////////////////////////////
void Motion(int x,int y)
{
if(mouseLeftDown)
{
cameraAngleY += (x - mouseX);
cameraAngleX += (y - mouseY);
mouseX = x;
mouseY = y;
}
if(mouseRightDown)
{
cameraDistance -= (y - mouseY) * 0.2f;
mouseY = y;
}
}
///////////////////////////////////////////////////////////////////////////////
// Funzione per rilevamento bottoni mouse
///////////////////////////////////////////////////////////////////////////////
void Mouse(int button, int state, int x, int y)
{
mouseX = x;
mouseY = y;
if(button == GLUT_LEFT_BUTTON)
{
if(state == GLUT_DOWN)
{
mouseLeftDown = true;
}
else if(state == GLUT_UP)
mouseLeftDown = false;
}
else if(button == GLUT_RIGHT_BUTTON)
{
if(state == GLUT_DOWN)
{
mouseRightDown = true;
}
else if(state == GLUT_UP)
mouseRightDown = false;
}
else if(button == GLUT_MIDDLE_BUTTON)
{
if(state == GLUT_DOWN)
{
mouseMiddleDown = true;
}
else if(state == GLUT_UP)
mouseMiddleDown = false;
}
}
///////////////////////////////////////////////////////////////////////////////
// Inizializzazione di GLUT
///////////////////////////////////////////////////////////////////////////////
void initGLUT(){
//parametri fake per il lancio di InitGlut
char *myargv[1];
int myargc = 1;
myargv[0]=strdup("MyOpenGL");
//Inizializzazione Glut basso livello
glutInit(&myargc,myargv);
//Lancio funzioni di settaggio finestra,visualizzazione ed altro
glutInitDisplayMode( GLUT_RGBA| GLUT_DOUBLE | GLUT_DEPTH |GLUT_STENCIL);
glutInitWindowSize(screenWidth, screenHeight);
glutInitWindowPosition(850,100);
glutCreateWindow("Ricostruzione attuale");
//callback delle funzioni richiamate
glutDisplayFunc(draw);
glutTimerFunc(33,timerCB,33);
glutReshapeFunc(reshape);
glutMouseFunc(Mouse);
glutMotionFunc(Motion);
}
///////////////////////////////////////////////////////////////////////////////
// Thread richiamato per lanciare OPENGL
///////////////////////////////////////////////////////////////////////////////
void DRAW3D (void *param){
//abbassa priorità del thread a backgroud
if(!SetThreadPriority(GetCurrentThread(), THREAD_MODE_BACKGROUND_BEGIN))
{
dwError = GetLastError();
if (ERROR_THREAD_MODE_ALREADY_BACKGROUND == dwError)
_tprintf(TEXT("Gia' in background\n"));
else _tprintf(TEXT("Errore nell'entrare in modalita' background (%d)\n"), dwError);
}
// Lancia funzione di inizializzazione variabili globali
initSharedMem();
//initiGLUT
initGLUT();
init();
//ciclo OpenGL
glutMainLoop();
_endthread();
}
其中 prova 它是一个立方体对象的矢量容器,该容器从一个类中实例化,该类通过 6 个顶点和一个边(lato)和级别的大小来定义立方体。
使用简单的第一级“读取和绘制”函数(没有递归性)删除递归函数“adddraw”解决了问题(窗口显示正确的 1° 级别立方体、可旋转、可缩放...没有崩溃或阻塞窗口)但是我需要在每个分支中绘制所有最大级别的立方体......所以我需要对向量进行递归扫描......
所以,我不知道这是怎么做到的……有人可以帮助我吗?
1) 如何仅在需要时刷新 OpenGL 绘图? 2) 如何用OpenGL线程绘制包含在多级向量中的一系列立方体?
我在 Windows 7 64 位、freeglut 2.8.1 下使用 Visual C++ 2010
【问题讨论】:
标签: c++ multithreading opengl