[实验]用VTK给立方体贴纹理

今天需要用vtk实现贴图功能,搜遍网上居然都没有找到很好的学习资料,只是找到一篇写于07年的“vtk中的纹理贴图详解”里面有一个例子,是在一个平面上贴图,但我要实现的是三维空间中的贴图,类似于在一个立方体上面贴图,有参考的例子了,开始实验:

1、VTK纹理贴图基础:

vtk中的纹理贴图详解(点击进入)

 

 

2、实验开始:

 

预定义

[cpp]  view plain copy
  1. #define NFACE 6  

  2. #define NLINE 4  
  3. #define M_GET_LENGTH3D(x, y, z)   sqrt((double)((x)*(x) + (y)*(y) + (z)*(z)))

    //---------------------------------------------------------  

  4. typedef struct _T_PT3D_T_  
  5. {  
  6.  double      x, y, z;  
  7. }  
  8. PT3D;

      


 

先是定义数据,先是生成一个vtkUnstructuredGrid的立方体数据

[cpp]  view plain copy
  1.  //首先定义立方体的8个点                    

  2.  //       a-----------b   //顶  
  3.  //       /           /  
  4.  //     /           /  
  5.  //     c-----------d

     //       aa-----------bb  //底  

  6.  //       /           /  
  7.  //     /           /  
  8.  //     cc-----------dd  
  9.  PT3D pa,pb,pc,pd,paa,pbb,pcc,pdd;  
  10.  paa.x = paa.y = paa.z = 0;  
  11.  pbb.x = pbb.z = 0; pbb.y = 1;  
  12.  pcc.y = pcc.z = 0; pcc.x = 1;  
  13.  pdd.x = pdd.y = 1; pdd.z = 0;  
  14.  pa.x = pa.y = 0; pa.z = 1;  
  15.  pb.y = pb.z = 1; pb.x = 0;  
  16.  pc.x = pc.z = 1; pc.y = 0;  
  17.  pd.x = pd.y = pd.z = 1;

     vtkUnstructuredGrid *mycube = vtkUnstructuredGrid::New();  

  18.  vtkPoints *points = vtkPoints::New();  
  19.  points->InsertPoint(0, paa.x, paa.y, paa.z);//0->aa  
  20.  points->InsertPoint(1, pbb.x, pbb.y, pbb.z);//1->bb  
  21.  points->InsertPoint(2, pcc.x, pcc.y, pcc.z);//2->cc  
  22.  points->InsertPoint(3, pdd.x, pdd.y, pdd.z);//3->dd  
  23.  points->InsertPoint(4, pa.x, pa.y, pa.z);//4->a  
  24.  points->InsertPoint(5, pb.x, pb.y, pb.z);//5->b  
  25.  points->InsertPoint(6, pc.x, pc.y, pc.z);//6->c  
  26.  points->InsertPoint(7, pd.x, pd.y, pd.z);//7->d  
  27.  mycube->SetPoints(points);  
  28.  //int facesIndex[6][4] = {{  下   },{  上   },{  左   },{  右   },{  前   },{  后   }};  
  29.  //int facesIndex[6][4] = {{aa-bb-dd-cc},{a-b-d-c},{aa-a-c-cc},{bb-b-d-dd},{cc-c-d-dd},{aa-a-b-bb}};  
  30.  int facesIndex[NFACE][NLINE] = {{0,1,3,2},{4,5,7,6},{0,4,6,2},{1,5,7,3},{2,6,7,3},{0,4,5,1}};  
  31.  //int facesIndex[NFACE][NLINE] = {{6,0,2},{6,0,1},{6,2,3},{6,1,3}};  
  32.    
  33.    
  34.  for (int iFace = 0; iFace < NFACE; iFace++)  
  35.  {  
  36.   mycube->InsertNextCell(VTK_POLYGON,NLINE,facesIndex[iFace]);  
  37.  }

      

 

然后读取纹理数据,纹理文件见附件

[cpp]  view plain copy
  1. //读取纹理图像  
  2. vtkBMPReader *bmpReader = vtkBMPReader::New();  
  3. bmpReader->SetFileName("D:\\CPlusPlusOpenSource\\MyTest\\01VTKtest\\test_project\\masonry.bmp");  
  4. vtkTexture *atext = vtkTexture::New();  
  5. atext->SetInputConnection(bmpReader->GetOutputPort());  
  6. atext->InterpolateOn();  


生成polydata

[cpp]  view plain copy
  1. //将点和多边形加入polydata  
  2.  vtkCellArray *faces = mycube->GetCells();  
  3.  vtkPolyData *profile = vtkPolyData::New();  
  4.  profile->SetPoints(points);  
  5.  profile->SetPolys(faces);  

 

纹理配制,这里面主要试验的就是tmapper三个参数的设置

[cpp]  view plain copy
  1. //计算多边形的发向量。  
  2.  vtkPolyDataNormals *normal = vtkPolyDataNormals::New();  
  3.  normal->SetInput(profile);  
  4.    
  5.  //设置多边形的纹理映射模式  
  6.  //设置为plane模式  
  7.  vtkTextureMapToPlane *tmapper = vtkTextureMapToPlane::New();  
  8.  tmapper->SetInputConnection(normal->GetOutputPort());  
  9.    
  10.  //设置纹理st坐标系的顶点坐标 和两点坐标,定义了st坐标系  
  11.  //下面这一部分就是下面要试验的!  
  12.  tmapper->SetOrigin(paa.x, paa.y, paa.z);  
  13.  tmapper->SetPoint1(pa.x, pa.y, pa.z);  
  14.  tmapper->SetPoint2(pbb.x, pbb.y, pbb.z);   
  15.  //对纹理映射进行计算  
  16.  vtkTransformTextureCoords *xform = vtkTransformTextureCoords::New();  
  17.  xform->SetInputConnection(tmapper->GetOutputPort());  
  18.  //设置贴图重复比例 第一项是指s 第二项是指t 第三项是指r 一般是1  
  19.  //14:1是根据上面点坐标的数据估算出来的。如果将t坐标定义为1,那么就将纹理向s方向贴14格,也就是说,纹理在这个面片上横着14张,这里因为是正方形直接用1,1  
  20.  xform->SetScale(10, 1, 1);  


最后是数据的显示

[cpp]  view plain copy
  1. //将数据放入polydata  
  2.  vtkPolyDataMapper *weightedTransMapper = vtkPolyDataMapper::New();  
  3.  weightedTransMapper->SetInputConnection(xform->GetOutputPort());  
  4.    
  5.  //将数据放入actor  
  6.  vtkActor *weightedTransActor = vtkActor::New();  
  7.  weightedTransActor->SetMapper(weightedTransMapper);  
  8.  weightedTransActor->SetTexture(atext);  
  9.    
  10.    
  11.  //进行显示  
  12.  vtkRenderer *ren1 = vtkRenderer::New();  
  13.  vtkRenderWindow *renWin = vtkRenderWindow::New();  
  14.  renWin->AddRenderer(ren1);  
  15.  vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New();  
  16.  vtkInteractorStyleTrackballCamera *style = vtkInteractorStyleTrackballCamera::New();  
  17.  iren->SetInteractorStyle(style);  
  18.  iren->SetRenderWindow(renWin); ren1->AddActor(weightedTransActor);  
  19.  //ren1->SetBackground(0.1, 0.2, 0.5);  
  20.  ren1->SetBackground(0.3, 0.3, 0.3);  
  21.  renWin->SetSize(788, 588);  
  22.    
  23.   ren1->GetActiveCamera()->Azimuth(90);  
  24.   ren1->GetActiveCamera()->Dolly(0);  
  25.  ren1->ResetCamera();  
  26.  ren1->GetActiveCamera()->Zoom(1);  
  27.    
  28.  iren->Initialize();  
  29.  iren->Start();  

3 实验结果

下面两个是实验不规则六面体和三角面贴图的效果

 

4 结果分析

基于上面的例子发现最后还是只能一片片贴,效率还是很低的,感觉这里面是要把不同的面片按照法线的方向来分类,一类用一个vtkTransformTextureCoords(vtkTextureMapToPlane),但不知道具体怎么操作~

5 源码

源码见附件,另外附件里的源码做了一个小小的优化,里面使用了vtkAppendPolyData把vtkTransformTextureCoords的结果append到一起,然后render,这样生成的速度还是很慢,但是至少交互的速度还行

啊,没找到传附件的地方。。。先插入纹理原件吧:(本来是bmp插进来变成jif自己转一下吧)

 

源码直接贴到下面吧,其实跟上面的步骤也差不多:

CubeTexture.cpp

 

[cpp]  view plain copy
  1.   
  2. //          vtk中的纹理贴图要用 vtkTextureMapToPlane vtkTextureMapToSphere        //  
  3. //              vtkTextureMapToCylinder与 vtkTransformTextureCoords                //  
  4. //                      配合使用才能达到最好的效果。                            //  
  5. //                                                                                //                                        
  6. //                  目前vtk只支持2维纹理,3维纹理似乎并不支持。                      //  
  7. //                                                                                //  
  8. //                      那么vtk的纹理是如何工作的呢??                             //  
  9. //                                                                                //  
  10. //                  那么我们通过自己的一段代码来解释一下:                       //  
  11. //                                                                                //  
  12. //               http://blog.csdn.net/yqxx/article/details/1671900                //  
  13. //                                                                                //  
  14. //                  在原代码的基础上修改成立方体贴纹理                             //  
  15. //                      2011年8月27日  [email protected]                           //  
  16.   
  17.   
  18. #include "vtkActor.h"   
  19. #include "vtkCamera.h"   
  20. #include "vtkBMPReader.h"   
  21. #include "vtkCellArray.h"   
  22. #include "vtkPoints.h"   
  23. #include "vtkPolyData.h"   
  24. #include "vtkPolyDataMapper.h"   
  25. #include "vtkPolyDataNormals.h"   
  26. #include "vtkRenderWindow.h"   
  27. #include "vtkRenderWindowInteractor.h"   
  28. #include "vtkRenderer.h"   
  29. #include "vtkTexture.h"   
  30. #include "vtkTextureMapToPlane.h"   
  31. #include "vtkTextureMapToSphere.h"   
  32. #include "vtkTransformTextureCoords.h"   
  33. #include "vtkTextureMapToCylinder.h"  
  34. #include "vtkProperty.h"   
  35. #include   
  36. #include   
  37. #include   
  38. #include   
  39. #include   
  40.   
  41. // #define NFACE 4  
  42. // #define NLINE 3  
  43. #define NFACE 6  
  44. #define NLINE 4  
  45. #define M_GET_LENGTH3D(x, y, z)         sqrt((double)((x)*(x) + (y)*(y) + (z)*(z)))  
  46.   
  47. //---------------------------------------------------------  
  48. typedef struct _T_PT3D_T_  
  49. {  
  50.     double                      x, y, z;  
  51. }  
  52. PT3D;  
  53.   
  54. int main()  
  55. {  
  56.     //首先定义立方体的8个点                    
  57.     //       a-----------b   //顶  
  58.     //       /           /  
  59.     //      /           /  
  60.     //     c-----------d  
  61.   
  62.     //       aa-----------bb  //底  
  63.     //       /           /  
  64.     //      /           /  
  65.     //     cc-----------dd  
  66.     PT3D pa,pb,pc,pd,paa,pbb,pcc,pdd;  
  67.     paa.x = paa.y = paa.z = 0;  
  68.     pbb.x = pbb.z = 0; pbb.y = 1;  
  69.     pcc.y = pcc.z = 0; pcc.x = 1;  
  70.     pdd.x = pdd.y = 1; pdd.z = 0;  
  71.     pa.x = pa.y = 0; pa.z = 1;  
  72.     pb.y = pb.z = 1; pb.x = 0;  
  73.     pc.x = pc.z = 1; pc.y = 0;  
  74.     pd.x = pd.y = pd.z = 1;  
  75.   
  76.     vtkUnstructuredGrid *mycube = vtkUnstructuredGrid::New();  
  77.     vtkPoints *points = vtkPoints::New();  
  78.     points->InsertPoint(0, paa.x, paa.y, paa.z);//0->aa  
  79.     points->InsertPoint(1, pbb.x, pbb.y, pbb.z);//1->bb  
  80.     points->InsertPoint(2, pcc.x, pcc.y, pcc.z);//2->cc  
  81.     points->InsertPoint(3, pdd.x, pdd.y, pdd.z);//3->dd  
  82.     points->InsertPoint(4, pa.x, pa.y, pa.z);//4->a  
  83.     points->InsertPoint(5, pb.x, pb.y, pb.z);//5->b  
  84.     points->InsertPoint(6, pc.x, pc.y, pc.z);//6->c  
  85.     points->InsertPoint(7, pd.x, pd.y, pd.z);//7->d  
  86.     mycube->SetPoints(points);  
  87.     //int facesIndex[6][4] = {{  下   },{  上   },{  左   },{  右   },{  前   },{  后   }};  
  88.     //int facesIndex[6][4] = {{aa-bb-dd-cc},{a-b-d-c},{aa-a-c-cc},{bb-b-d-dd},{cc-c-d-dd},{aa-a-b-bb}};  
  89.     int facesIndex[NFACE][NLINE] = {{0,1,3,2},{4,5,7,6},{0,4,6,2},{1,5,7,3},{2,6,7,3},{0,4,5,1}};  
  90.     //int facesIndex[NFACE][NLINE] = {{6,0,2},{6,0,1},{6,2,3},{6,1,3}};  
  91.       
  92.       
  93.     for (int iFace = 0; iFace < NFACE; iFace++)  
  94.     {  
  95.         mycube->InsertNextCell(VTK_POLYGON,NLINE,facesIndex[iFace]);  
  96.     }  
  97.   
  98.     //使用vtkUnstructuredGrid是为了跟我后面要写的程序对接,实际上可以直接通过下面的方式定义顶点索引  
  99.     //vtkCellArray *faces = vtkCellArray::New();  
  100.     //faces->InsertNextCell(4);//face aa-bb-cc-dd(下)  
  101.     //faces->InsertCellPoint(0);  
  102.     //faces->InsertCellPoint(1);  
  103.     //faces->InsertCellPoint(2);  
  104.     //faces->InsertCellPoint(3);  
  105.   
  106.     //faces->InsertNextCell(4);//face a-b-c-d(上)  
  107.     //faces->InsertCellPoint(4);  
  108.     //faces->InsertCellPoint(5);  
  109.     //faces->InsertCellPoint(6);  
  110.     //faces->InsertCellPoint(7);  
  111.   
  112.     //faces->InsertNextCell(4);//face aa-a-c-cc(左)  
  113.     //faces->InsertCellPoint(0);  
  114.     //faces->InsertCellPoint(4);  
  115.     //faces->InsertCellPoint(6);  
  116.     //faces->InsertCellPoint(2);  
  117.   
  118.     //faces->InsertNextCell(4);//face bb-b-d-dd(右)  
  119.     //faces->InsertCellPoint(1);  
  120.     //faces->InsertCellPoint(5);  
  121.     //faces->InsertCellPoint(7);  
  122.     //faces->InsertCellPoint(3);  
  123.   
  124.     //faces->InsertNextCell(4);//face cc-c-d-dd(前)  
  125.     //faces->InsertCellPoint(2);  
  126.     //faces->InsertCellPoint(6);  
  127.     //faces->InsertCellPoint(7);  
  128.     //faces->InsertCellPoint(3);  
  129.   
  130.     //faces->InsertNextCell(4);//face aa-a-b-bb(后)  
  131.     //faces->InsertCellPoint(0);  
  132.     //faces->InsertCellPoint(4);  
  133.     //faces->InsertCellPoint(5);  
  134.     //faces->InsertCellPoint(1);  
  135.   
  136.     //读取纹理图像  
  137.     vtkBMPReader *bmpReader = vtkBMPReader::New();  
  138.     bmpReader->SetFileName("D:\\CPlusPlusOpenSource\\MyTest\\01VTKtest\\test_project\\masonry.bmp");  
  139.     vtkTexture *atext = vtkTexture::New();  
  140.     atext->SetInputConnection(bmpReader->GetOutputPort());  
  141.     atext->InterpolateOn();  
  142.       
  143.     //将点和多边形加入polydata  
  144.     vtkCellArray *faces = mycube->GetCells();  
  145.     //vtkPolyData *profile = vtkPolyData::New();  
  146.     vtkIdType *indices;  
  147.     vtkIdType numberOfPoints;  
  148.     PT3D pt0,pt1,pt2;  
  149.     //vtkAssembly * CubeAssembly = vtkAssembly::New();  
  150.     vtkAppendPolyData * CaVectorAppendPoly = vtkAppendPolyData::New();  
  151.     for (faces->InitTraversal();faces->GetNextCell(numberOfPoints, indices);)  
  152.     {  
  153.         vtkPolyData *profile = vtkPolyData::New();  
  154.         vtkCellArray *lines = vtkCellArray::New();  
  155.         lines->InsertNextCell(numberOfPoints);//#number of points  
  156.         for (vtkIdType i = 0; i < numberOfPoints; i++)  
  157.         {  
  158.             lines->InsertCellPoint(indices[i]);  
  159.             //lines->InsertCellPoint(i);  
  160.             double point[3];  
  161.             points->GetPoint(indices[i], point);  
  162.             if (numberOfPoints < 4)  
  163.             {  
  164.                 if (i == 1)  
  165.                 {  
  166.                     pt0.x = point[0];pt0.y = point[1];pt0.z = point[2];  
  167.                 }  
  168.                 if (i == 2)  
  169.                 {  
  170.                     pt1.x = point[0];pt1.y = point[1];pt1.z = point[2];  
  171.                 }  
  172.                 if (i == 0)  
  173.                 {  
  174.                     pt2.x = point[0];pt2.y = point[1];pt2.z = point[2];  
  175.                 }  
  176.             }  
  177.             else //提供对三角面片的支持  
  178.             {  
  179.                 if (i == 0)  
  180.                 {  
  181.                     pt0.x = point[0];pt0.y = point[1];pt0.z = point[2];  
  182.                 }  
  183.                 if (i == 1)  
  184.                 {  
  185.                     pt1.x = point[0];pt1.y = point[1];pt1.z = point[2];  
  186.                 }  
  187.                 if (i == 3)  
  188.                 {  
  189.                     pt2.x = point[0];pt2.y = point[1];pt2.z = point[2];  
  190.                 }  
  191.   
  192.             }  
  193.         }  
  194.         profile->SetPoints(points);  
  195.         profile->SetPolys(lines);  
  196.   
  197.         //计算多边形的法向量。  
  198.         vtkPolyDataNormals *normal = vtkPolyDataNormals::New();  
  199.         normal->SetInput(profile);  
  200.   
  201.         //设置多边形的纹理映射模式  
  202.         //设置为plane模式  
  203.         vtkTextureMapToPlane *tmapper = vtkTextureMapToPlane::New();  
  204.         tmapper->SetInputConnection(normal->GetOutputPort());  
  205.   
  206.         //设置纹理st坐标系的顶点坐标 和两点坐标,定义了st坐标系  
  207.         tmapper->SetOrigin(pt0.x, pt0.y, pt0.z);  
  208.         tmapper->SetPoint1(pt1.x, pt1.y, pt1.z);  
  209.         tmapper->SetPoint2(pt2.x, pt2.y, pt2.z);  
  210.   
  211.         //对纹理映射进行计算  
  212.         vtkTransformTextureCoords *xform = vtkTransformTextureCoords::New();  
  213.         xform->SetInputConnection(tmapper->GetOutputPort());  
  214.         //设置贴图重复比例 第一项是指s 第二项是指t 第三项是指r 一般是1  
  215.         //14:1是根据上面点坐标的数据估算出来的。如果将t坐标定义为1,那么就将纹理向s方向贴14格,也就是说,纹理在这个面片上横着14张  
  216.         xform->SetScale(1, 1, 1);  
  217.           
  218.         //append,这样只需要一个actor  
  219.         CaVectorAppendPoly->AddInput((vtkPolyData*)xform->GetOutput());  
  220.     }  
  221.           
  222.     //将数据放入polydata  
  223.     vtkPolyDataMapper *weightedTransMapper = vtkPolyDataMapper::New();  
  224.     weightedTransMapper->SetInputConnection(CaVectorAppendPoly->GetOutputPort());  
  225.   
  226.     //将数据放入actor  
  227.     vtkActor *weightedTransActor = vtkActor::New();  
  228.     weightedTransActor->SetMapper(weightedTransMapper);  
  229.     weightedTransActor->SetTexture(atext);  
  230.   
  231.     atext->Delete();  
  232.     points->Delete();  
  233.   
  234.     //进行显示  
  235.     vtkRenderer *ren1 = vtkRenderer::New();  
  236.     vtkRenderWindow *renWin = vtkRenderWindow::New();  
  237.     renWin->AddRenderer(ren1);  
  238.     vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New();  
  239.     vtkInteractorStyleTrackballCamera *style = vtkInteractorStyleTrackballCamera::New();  
  240.     iren->SetInteractorStyle(style);  
  241.     iren->SetRenderWindow(renWin);  
  242.   
  243.     //ren1->AddActor(weightedTransActor);  
  244.     ren1->AddActor(weightedTransActor);  
  245.     //ren1->SetBackground(0.1, 0.2, 0.5);  
  246.     ren1->SetBackground(0.3, 0.3, 0.3);  
  247.     renWin->SetSize(788, 588);  
  248.       
  249.     ren1->GetActiveCamera()->Azimuth(90);  
  250.     ren1->GetActiveCamera()->Dolly(0);  
  251.     ren1->ResetCamera();  
  252.     ren1->GetActiveCamera()->Zoom(1);  
  253.       
  254.     iren->Initialize();  
  255.     iren->Start();  
  256.       
  257.     return 0;  
  258. }  
From:  http://blog.csdn.net/nowen/article/details/6725760

你可能感兴趣的:(computer,graphics)