0

我正在使用 Assimp 加载 .3ds 文件,并使用 QGLWidget 派生类使用 PaintGL() 绘制它。它适用于小的 .3ds 文件(一些 KBytes),但如果我尝试渲染更大的文件(如 1MBytes),应用程序会崩溃。我的方式太糟糕和扭曲了吗?难道我做错了什么?

使用 qDebug,我知道 paintGL() 可以正常工作。问题出在我们的 Render 方法中,因为如果我掩盖了

for (int t = 0; t < p->getFaces().count(); ++t)

并详细

glVertex3f(f.getVerticesArray()[s].getX(),f.getVerticesArray();

循环它所有的工作都很快(但显然什么都没有画)除了网格和轴。有了它,加载一些复杂的 3ds,它崩溃了

我的硬件是

Phenom II X3 2.10ghz,4GB and 6650M (last drivers)

在 Celeron 2.1 Ghz 上它崩溃但在 i7 上程序启动但渲染 @2FPS(如果我不使用“ourRender”方法,它在我的电脑上以 120fps 渲染)

void GLWidget::paintGL()
{
qDebug << "Start PaintGL() #" << times;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();

gluLookAt(objCamera->mPos.x,  objCamera->mPos.y,  objCamera->mPos.z,
              0, objCamera->mView.y, 0,
              objCamera->mUp.x,   objCamera->mUp.y,   objCamera->mUp.z);        

if (drawLines) glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
else glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);

draw_grid();
drawAxis();

ourRender(this->scenaa);
qDebug << "Close PaintGL() #" << times;
}

这是“ourRender”方法:

void GLWidget::ourRender(const Scene* sc){

QHash<QString, SceneObject*>& hash=sc->getObj();
double molt =1/20;
int counter =0;
for (QHash<QString,SceneObject*>::ConstIterator i = hash.begin();i!=hash.end();++i) {
    aiMatrix4x4 minchia(1,0,0,molt*20,0,1,0,molt*20,0,0,1,molt*20,0,0,0,1);
    aiTransposeMatrix4(&minchia);
    glPushMatrix();
    const Mesh* p = dynamic_cast<Mesh*>(i.value());
    glMultMatrixf((float*) &minchia);
    if(p){
        for (int t = 0; t < p->getFaces().count(); ++t) {
            Face f = p->getFaces()[t];
            GLenum face_mode;
            switch(f.getVerticesArray().count()) {
            case 1: face_mode = GL_POINTS; break;
            case 2: face_mode = GL_LINES; break;
            case 3: face_mode = GL_TRIANGLES; break;
            default: face_mode = GL_POLYGON; break;
            }
            glBegin(face_mode);
            QList<Vector3D> lista = f.getVerticesArray();
            for(int s = 0; s < lista.count(); s++) {
                if (p->getNormals().count()>0)
      --------->glVertex3f(f.getVerticesArray()[s].getX(),f.getVerticesArray()[s].getY(),f.getVerticesArray()[s].getZ());
            }
            glEnd();
        }
    }
    glPopMatrix();
    molt+=13;
    counter++;
}
glPopMatrix();
}

...在派生的 QGLWidget 类构造函数中...

SceneImporter* aa = new AssimpAdapter();
Scene * nuovo=aa->importFile("C:/Users/nicola/Desktop/Source/aces.3ds");
scenaa=nuovo;
4

2 回答 2

0

优化。事实是,对于每个顶点,我们访问 QList 3 次。现在我们修改了它,我们使用 Vector3D* 数组代替 Qlist,它保存顶点的位置,因此我们可以使用 GL 方法glVertex3fv((GLfloat*)array[numface].posvertex); 因此,给定指向脸部的指针,它比以前快得多(在同一场景中为 4 到 10 fps)。

void GLWidget::ourRender(Scene *sc){
QHash<QString, SceneObject*>& hash=sc->getObj();
aiMatrix4x4 m;
for (QHash<QString,SceneObject*>::ConstIterator i = hash.begin();i!=hash.end();++i) {

    aiTransposeMatrix4(&m);
    glPushMatrix();
    Mesh* p = dynamic_cast<Mesh*>(i.value());
    glMultMatrixf((float*) &m);
    if(p){
        QList<Face>& faccie=p->getFaces();
        int numerofacce=faccie.count();
        for (int t = 0; t < numerofacce; ++t) {
            Face& f = faccie[t];
            GLenum face_mode;
            Vector3D* lista=f.arrayVertici;

            switch(f.getVerticesArray().count()) {
            case 1:
                face_mode = GL_POINTS;
                glBegin(face_mode);
                glVertex3fv((GLfloat*)lista[0].pos);
                break;
            case 2:
                face_mode = GL_LINES;
                glBegin(face_mode);
                glVertex3fv((GLfloat*)lista[0].pos);
                glVertex3fv((GLfloat*)lista[1].pos);
                break;
            case 3:
                face_mode = GL_TRIANGLES;
                glBegin(face_mode);
                glVertex3fv(&lista[0].pos[0]);
                glVertex3fv(&lista[1].pos[0]);
                glVertex3fv(&lista[2].pos[0]);
                break;
            default: face_mode = GL_POLYGON; break;
            }
            glEnd();
        }
    }
    glPopMatrix();
    counter++;
}
glPopMatrix();

}

Vector3D 的初始化如下:

Vector3D::Vector3D(double x, double y, double z) {
setX(x);
setY(y);
setZ(z);
pos[0]=x;   //vertex1
pos[1]=y;   //vertex2
pos[2]=z;   //vertex3
}

PS:Grimmy 建议我使用 DisplayLists(现在发现)。明天我会尝试它们。

于 2013-05-25T00:25:13.247 回答
0

我们解决了修改“ourender”方法的问题(使用引用而不是副本)

void GLWidget::ourRender(Scene *&sc){

QHash<QString, SceneObject*>& hash=sc->getObj();
int counter =0;
for (QHash<QString,SceneObject*>::ConstIterator i = hash.begin();i!=hash.end();++i) {
    aiMatrix4x4 m;
    aiTransposeMatrix4(&m);
    glPushMatrix();
    const Mesh* p = dynamic_cast<Mesh*>(i.value());
    glMultMatrixf((float*) &m);
    if(p){
        //apply_material(aaFuori.GetScene()->mMaterials[counter]);
        QList<Face>& faccie=p->getFaces();
        for (int t = 0; t < faccie.count(); ++t) {
            Face f = faccie[t];
            GLenum face_mode;
            switch(f.getVerticesArray().count()) {
            case 1: face_mode = GL_POINTS; break;
            case 2: face_mode = GL_LINES; break;
            case 3: face_mode = GL_TRIANGLES; break;
            default: face_mode = GL_POLYGON; break;
            }
            glBegin(face_mode);
            QList<Vector3D>& lista = f.getVerticesArray();
            int conta=lista.count();
            glVertex3f(lista[0].x,lista[0].y,lista[0].z);
            glVertex3f(lista[1].x,lista[1].y,lista[1].z);
            glVertex3f(lista[2].x,lista[2].y,lista[2].z);
            glEnd();
        }
    }
    glPopMatrix();
    counter++;
}

现在我们可以在相机旋转期间渲染 8MBytes .3Ds @4fps(而不是应用程序崩溃)。你们中的某个人可以给我们关于这个结果的意见吗?是好是坏?

于 2013-05-23T09:06:20.690 回答