三角形带优化库nvtrisrip的使用

简介:

nvtrisrip是NVIDIA提供的一个开源优化库,这个库可以将三角形顶点索引数组转换为三角形带索引数组。可以极大的提高渲染速度。

NVIDIA这个库的官方地址是:
http://www.nvidia.com/object/nvtristrip_library.html

不过这里代码不全也不够新,推荐从GitHub上下载:
https://github.com/turbulenz/NvTriStrip

下载完毕后,我们把下面文件夹中的源代码加入到项目中:
/NvTriStrip/include
/NvTriStrip/src

一共为6个文件 

wKiom1PquBnSAJ3SAADLMJA9i5A259.jpg


需要注意的是VertexCache类有个非常奇怪的设计,在.h和.cpp中同时有两套实现代码。这会导致重定义,我们可以把.h中的代码注释起来。另外还需要修改entries变量为unsign short类型。 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
#ifndef VERTEX_CACHE_H
  
#define VERTEX_CACHE_H
  
#include <string.h>
  
class  VertexCache
{
      
public :
      
     VertexCache( int  size);
//  {
//      numEntries = size;
//     
//      entries = new int[numEntries];
//     
//      for(int i = 0; i < numEntries; i++)
//          entries[i] = -1;
//  }
          
     VertexCache(); // { VertexCache(16); }
     ~VertexCache(); // { delete[] entries; entries = 0; }
      
     bool  InCache( int  entry);
//  {
//      bool returnVal = false;
//      for(int i = 0; i < numEntries; i++)
//      {
//          if(entries[i] == entry)
//          {
//              returnVal = true;
//              break;
//          }
//      }
//     
//      return returnVal;
//  }
      
     int  AddEntry( int  entry);
//  {
//      int removed;
//     
//      removed = entries[numEntries - 1];
//     
//      //push everything right one
//      for(int i = numEntries - 2; i >= 0; i--)
//      {
//          entries[i + 1] = entries[i];
//      }
//     
//      entries[0] = entry;
//     
//      return removed;
//  }
  
     void  Clear();
//  {
//      memset(entries, -1, sizeof(int) * numEntries);
//  }
      
     void  Copy(VertexCache* inVcache) ;
//  {
//      for(int i = 0; i < numEntries; i++)
//      {
//          inVcache->Set(i, entries[i]);
//      }
//  }
  
     int  At( int  index); // { return entries[index]; }
     void  Set( int  index,  int  value); // { entries[index] = value; }
  
private :
  
//  int *entries;
   //此处修改为unsigned short
   unsigned  short  *entries;
   int  numEntries;
  
};
  
#endif


我们看一下在SIO2中的使用,其他引擎中的用法,大同小异

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
void  ObjMod::optimize_mesh(unsigned  int  mesh_index, unsigned  int  vertex_cache_size) {
     ObjMesh *objmesh = & this ->objmesh[ mesh_index ];
       
     unsigned  int  i = 0,
     s = 0;
       
     unsigned  short  n_group = 0;
       
     //设置顶点缓存大小,顶点缓存越大,优化时间越长,优化效果越好,但是成边界递减关系
     if ( vertex_cache_size )
         SetCacheSize( vertex_cache_size );
       
     while ( i != objmesh->n_objtrianglelist )
     {
         PrimitiveGroup *primitivegroup;
           
         //通过三角形索引创建
         //四个参数依次:被优化的三角形索引数组,三角形索引元素数量,优化后的三角形带数组,优化后的三角形带元素个数
         if ( GenerateStrips( objmesh->objtrianglelist[ i ].indice_array,
                            objmesh->objtrianglelist[ i ].n_indice_array,
                            &primitivegroup,
                            &n_group,
                            true  ) )
         {
             if ( primitivegroup[ 0 ].numIndices < objmesh->objtrianglelist[ i ].n_indice_array )
             {
                 objmesh->objtrianglelist[ i ].mode = GL_TRIANGLE_STRIP; //渲染模式修改为三角形带
                 objmesh->objtrianglelist[ i ].n_indice_array = primitivegroup[ 0 ].numIndices; //重置数据数量
                   
                 //重新申请内存//
                 s = primitivegroup[ 0 ].numIndices *  sizeof ( unsigned  short  );
                   
                 //这块使用realloc有点浪费空间,因为优化后的三角形带占用内存比原先的三角形索引要小
                 objmesh->objtrianglelist[ i ].indice_array = ( unsigned  short  * )  realloc ( objmesh->objtrianglelist[ i ].indice_array,
                                                                                           s );
                 //复制数据
                 memcpy ( &objmesh->objtrianglelist[ i ].indice_array[ 0 ],
                        &primitivegroup[ 0 ].indices[ 0 ],
                        s );
             }
               
             //删除优化后的临时数据
             delete [] primitivegroup;
         }
           
         ++i;
     }
}

我们这里调用库的函数有两个:
SetCacheSize为设置优化库使用的缓存大小并非越大越好。而是根据模型精细度来考量的。
GenerateStrips就是核心的三角形优化算法了。

然后保存输出的数据删掉临时数据即可。

下面是一个测试报告,画面数为4726个三角形的静态模型。重复绘制模型200次,在iPad mini2上面的结果是:

未开三角形带优化时的FPS: 

wKioL1PquzzxRsmCAACCJEY15UI417.jpg


开启三角形带优化之后的FPS:

wKiom1PqujvgwvlUAABx1oF2I8w710.jpg


FPS提高了70%,效果还是非常明显的。


在这里为了方便,我们使用的是在线优化方式(模型数据加载进内存后再优化)。而实际开发中,往往多使用离线优化,预先处理好模型数据,然后直接调用渲染就可以了,这样没有缓存和时间限制,效果更好。

这个库是平台无关,也没有第三方依赖,可以很方便的集成到自己的工具中去。 






 本文转自 老G 51CTO博客,原文链接:http://blog.51cto.com/goldlion/1539218,如需转载请自行联系原作者


相关文章
|
6月前
|
算法 C++ 计算机视觉
OpenCV-图像像素遍历操作的三种方法对比(程序提速)
OpenCV-图像像素遍历操作的三种方法对比(程序提速)
|
9月前
ArcGIS:如何进行离散点数据插值分析(IDW)、栅格数据的重分类、栅格计算器的简单使用、缓冲区分析、掩膜?
ArcGIS:如何进行离散点数据插值分析(IDW)、栅格数据的重分类、栅格计算器的简单使用、缓冲区分析、掩膜?
235 0
|
8月前
|
存储 Go
速绘丨GO富集气泡图绘制方法,利用R语言ggplot2包快速绘制,完整脚本可重复绘图
速绘丨GO富集气泡图绘制方法,利用R语言ggplot2包快速绘制,完整脚本可重复绘图
|
JSON 前端开发 数据可视化
【图形基础篇】02 # 指令式绘图系统:如何用Canvas绘制层次关系图?
【图形基础篇】02 # 指令式绘图系统:如何用Canvas绘制层次关系图?
143 0
【图形基础篇】02 # 指令式绘图系统:如何用Canvas绘制层次关系图?
python 如何通过海表面高度数据计算海表地转流速、并绘制流线图
最近,学习海气相互作用时,老师布置了一个小作业。通过卫星高度计测得的海表面高度异常数据,计算其表层地转流速,并研究其与海表面高度异常的关系。
python 如何通过海表面高度数据计算海表地转流速、并绘制流线图
|
NoSQL 定位技术 C#
基于C#的ArcEngine二次开发28: 等高线高程值与国标码一致性检查思路及代码分析
基于C#的ArcEngine二次开发28: 等高线高程值与国标码一致性检查思路及代码分析
基于C#的ArcEngine二次开发28: 等高线高程值与国标码一致性检查思路及代码分析
python读取excel数据、转换度分为度,绘制填色图
python读取excel数据、转换度分为度,绘制填色图
|
数据处理 Python
python 将垂直速度从压力坐标系转为高度坐标系(pa/s转为m/s)
最近在计算一下涡度的垂直项时,发现一个问题,如果使用笛卡尔坐标系下的涡度计算公式,会发现对于我们从ERA5下载的垂向速度ω,它的单位是:pa/s,而对于水平的速度u、v来说,它们的单位是:m/s,这在计算速度的旋度时就会出现问题,由于单位不一致引起计算无法进行,对于后续数据处理造成干扰。
python 将垂直速度从压力坐标系转为高度坐标系(pa/s转为m/s)
|
Rust 自然语言处理 算法
【算法】1725. 可以形成最大正方形的矩形数目(多语言实现)
给你一个数组 rectangles ,其中 rectangles[i] = [li, wi] 表示第 i 个矩形的长度为 li 、宽度为 wi 。 如果存在 k 同时满足 k <= li 和 k <= wi ,就可以将第 i 个矩形切成边长为 k 的正方形。例如,矩形 [4,6] 可以切成边长最大为 4 的正方形。 设 maxLen 为可以从矩形数组 rectangles 切分得到的 最大正方形 的边长。 请你统计有多少个矩形能够切出边长为 maxLen 的正方形,并返回矩形 数目 。
案例分享:Qt+OSG三维点云引擎(支持原点,缩放,单独轴或者组合多轴拽拖旋转,支持导入点云文件)
案例分享:Qt+OSG三维点云引擎(支持原点,缩放,单独轴或者组合多轴拽拖旋转,支持导入点云文件)
案例分享:Qt+OSG三维点云引擎(支持原点,缩放,单独轴或者组合多轴拽拖旋转,支持导入点云文件)

热门文章

最新文章