2017-06-28 2 views
0

Je simplifie la lecture et la visualisation d'un maillage.Rendu d'un maillage avec l'API VTK

VTK est nouveau pour moi et je suis d'abord en train d'essayer de trouver le moyen le meilleur/le plus efficace pour configurer les données de maillage pour le spectateur. Je vois qu'il y a beaucoup d'exemples de VTK avec C++, mais beaucoup d'entre eux doivent être convertis en format vtk ou en primitives de rendu.

Je ne suis pas intéressé à convertir au format VTK, je viens de mettre en place ce que mes données de maillage à un maillage non structuré de VTK ou données VTK poly mis et de le rendre.

J'ai fait un petit test. Le code ci-dessous s'affiche correctement, mais est-ce le moyen le plus efficace de configurer l'ensemble de données? Si je mets N_SQUARES à 1 000 000, cela fonctionne, mais la boucle triangulaire semble très lente.

vtkSmartPointer<vtkRenderer> renderer = vtkSmartPointer<vtkRenderer>::New(); 


    //TEST MESH 
    int N_SQUARES = 100; 

    //This creates node coordinates for N_SQUARES amount of squares. (Nodal data would be read from a file later on) 
    vtkSmartPointer<vtkPoints> nodes = vtkSmartPointer<vtkPoints>::New(); 

    for (int i = 0; i < N_SQUARES; i++){ 
     nodes->InsertNextPoint(0.0, 0.0, 0.0 + 0.2f*float(i)); 
     nodes->InsertNextPoint(1.0, 0.0, 0.0 + 0.2f*float(i)); 
     nodes->InsertNextPoint(1.0, 1.0, 0.0 + 0.2f*float(i)); 
     nodes->InsertNextPoint(0.0, 1.0, 0.2 + 0.2f*float(i)); 
    } 

    //Here two triangles are created for each square. (these indices would later on be read from FEM element data) 
    vtkSmartPointer<vtkCellArray> triangles = vtkSmartPointer<vtkCellArray>::New(); 

    for (int j = 0; j < N_SQUARES; j++){ 
     vtkSmartPointer<vtkTriangle> triangle1 = vtkSmartPointer<vtkTriangle>::New(); 
     triangle1->GetPointIds()->SetId(0, 0 + j); 
     triangle1->GetPointIds()->SetId(1, 1 + j); 
     triangle1->GetPointIds()->SetId(2, 2 + j); 

     vtkSmartPointer<vtkTriangle> triangle2 = vtkSmartPointer<vtkTriangle>::New(); 
     triangle2->GetPointIds()->SetId(0, 2 + j); 
     triangle2->GetPointIds()->SetId(1, 3 + j); 
     triangle2->GetPointIds()->SetId(2, 0 + j); 


     triangles->InsertNextCell(triangle1); 
     triangles->InsertNextCell(triangle2); 
    } 

    vtkSmartPointer<vtkPolyData> meshData = vtkSmartPointer<vtkPolyData>::New(); 
    meshData->SetPoints(nodes); 
    meshData->SetPolys(triangles); 

    vtkSmartPointer<vtkPolyDataMapper> meshMapper = vtkSmartPointer<vtkPolyDataMapper>::New(); 
    meshMapper->SetInputData(meshData); 

    vtkSmartPointer<vtkActor> meshActor = vtkSmartPointer<vtkActor>::New(); 
    meshActor->SetMapper(meshMapper); 

    renderer->AddActor(meshActor); 


    ui.qvtkWidget->GetRenderWindow()->AddRenderer(renderer); 

Répondre

1

Le code dans votre exemple pourrait être lent pour l'une des plusieurs raisons

  • Vous construisez et 2 instances vtkTriangle détruire l'intérieur de votre j -loop. C'est cher et probablement la plus grande cause de lenteur.
  • Étant donné que vous créez des polydonnées, il est préférable d'éviter d'utiliser vtkTriangle. Au lieu de cela, faire quelque chose comme

    for (int j = 0; j < N_SQUARES; ++j) 
    { 
        vtkIdType triangle1[3] = {j, j+1, j+2}; 
        vtkIdType triangle2[3] = {j+2, j+3, j}; 
        triangles->InsertNextCell(3, triangle1); 
        triangles->InsertNextCell(3, triangle2); 
        // ... or better yet, create a single quad: 
        vtkIdType quad[4] = {j, j+1, j+2, j+3}; 
        triangles->InsertNextCell(4, quad); 
    } 
    
  • Vous ne dites pas VTK la taille des tableaux (coordonnées du point ou la connectivité) vont être à l'avance. Cela signifie que VTK doit réaffecter et copier les tableaux lorsque vous augmentez leur taille. Essayez d'ajouter nodes->GetData()->Allocate(4 * N_SQUARES); avant votre première boucle (sur i). De même, vous pouvez dire à vtkCellArray d'allouer la bonne quantité de mémoire à l'avance (un peu compliqué, c'est un tableau d'entiers formatés comme ceci: nptsPerPoly0 ptId0Poly0 ptId1Poly0 ... ptIdNPoly0 nPtsPerPoly1 ...). Pour les triangles, vous appelez triangles->Allocate((1 + 3) * 2 * N_SQUARES);. Pour les quads comme dans l'exemple précédent, ce serait triangles->Allocate((1 + 4) * N_SQUARES);.

  • Votre exemple ne réutilise pas les points partagés par plusieurs carrés. Cela fait à la fois nodes et triangles consomment beaucoup plus de mémoire que nécessaire.
  • Pour les maillages de taille moyenne (installés en mémoire sur un seul ordinateur), vous pouvez utiliser le filetage pour préparer les baies nodes et triangles. Pour les maillages de grande taille, VTK est conçu pour fonctionner sur plusieurs ordinateurs où chacun ne contient qu'une partie du maillage (parallélisme à mémoire distribuée).
  • Si vous avez déjà le maillage en mémoire, les versions récentes de VTK vous permettent d'écrire des classes spéciales qui exposent le maillage à VTK sans nécessiter de copie, mais cela dépasse le cadre de cette question. Cependant, cela réduirait de moitié la quantité de mémoire consommée par un maillage, cela pourrait donc être important en fonction du maillage et de la mémoire de votre ordinateur.
  • En fonction de la taille du fichier N_SQUARES, votre ordinateur peut utiliser un fichier d'échange ou une partition. Dans ce cas, vous devez réduire la taille de votre maillage ou utiliser le parallélisme à mémoire distribuée.
+0

Merci beaucoup! C'est le genre de réponse dont j'avais besoin. Je vais modifier mon code et le tester. J'ai une certaine expérience avec OpenGL et l'utilisation de tampon et ainsi de suite pour le rendu. Je crois que "sous le capot" VTK l'utilise. Existe-t-il un aperçu de la manière dont VTK invoque les différentes méthodes OpenGL? – remi000

+0

@ remi000 Tous les appels OpenGL de VTK sont confinés aux classes dans les répertoires 'VTK/Rendering/OpenGL' ou' VTK/Rendering/OpenGL2' (selon que vous utilisez l'ancien ou le nouveau backend OpenGL. Les appels à OpenGL sont répartis sur plusieurs classes: par exemple, 'vtkOpenGLPolyDataMapper.cxx' remplit les instances' vtkOpenGLVertexBufferObject' avec des données, les appels qui lient/téléchargent les objets tampon sont dans 'vtkOpenGLBufferObject' (la superclasse de' vtkOpenGLVertexBufferObject'). – Drone2537