- 写于2024/08/13
无论在学什么之前,首先要了解你要去探索的东西它的一些特性,用途,把它的骨架画好,再基于这个骨架去逐步完善和修改。本系列博客将带你先去了解VCGLib
,再去完成在Visual Studio中的基本配置,之后进行示例的阅读与代码实践。
一、什么是VCG
1.背景
VCGLib
,全称为“Visualization and Computer Graphics Library”,是一个专门为处理三维数据而设计的开源C++库,它提供了丰富的算法和数据结构,在计算机视觉、图形处理和三维建模领域中是一个非常优秀的工具。
它是由意大利的Pisa大学视觉计算小组(Visual Computing Lab of the University of Pisa)开发并维护,并且它也是意大利国家研究委员会(CNR)下属的ISTI研究所视觉计算实验室(Visual Computing Lab of the Italian National Research Council Institute - ISTI)中大部分软件工具的基础库,如广受欢迎的MeshLab、Metro等。
目前,该库的代码以逾十万行,并以GPL-3.0许可协议发布。
2.功能
该库主要为管理三角形网格而定制,提供了许多处理网格的最新功能:
- high quality quadric-error edge-collapse based simplfication
基于高质量二次误差的边缘折叠网格简化 - efficient spatial query structures (uniform grids, hashed grids, kdtree, etc)
高效的空间查询结构(均匀网格,哈希网格,KD树等) - advanced smoothing and fairing algorithms
先进网格平滑和fairing算法 - computation of curvature
曲率计算 - optimization of texture coordinates
纹理坐标优化 - Hausdorff distance computation
Hausdorff距离计算 - geodesic paths
测地路径 - mesh repairing capabilities
网格修复能力 - isosurface extraction and advancing front meshing algorithms
等值面提取和前沿的网格划分算法 - Poisson Disk sampling and other tools to sample point distributions over meshes
泊松圆盘采样及其他网格上点分布采样工具 - subdivision surfaces
细分曲面处理
3.特性
- 高效的数据结构
- 丰富的算法
- 多样化的三维网格处理功能
- C++20现代设计
- 模块化设计
- 跨平台支持
- 开源和可扩展性
4.应用
在现有的开源三维网格处理软件中,MeshLab可以说也是独树一帜了,该软件就是基于VCGLib开发,其广泛应用于点云、网格等数据的处理,具备开源、跨平台的特性。除此之外,ISTI视觉计算实验室还基于VCGLib开发了优秀的Metro工具,这也证明了VCGLib的强大和灵活性。
对于那些希望在自己的项目中使用 MeshLab 提供的功能,但又需要进行更深度的定制或自动化处理的用户,直接使用 VCGLib 进行开发是一个更合适的选择。这也是为什么 VCGLib 和 MeshLab 常常一起被提及的原因。
二、环境配置
VCGLib 采用了面向对象的编程范式,并以模板库的形式实现。这意味着它是一个“头文件库”(header-only),在进行开发时我们只需包含相应的头文件即可使用库中的功能,无需进行额外的编译,这对于新手来说,大大降低了上手难度。
1.下载VCGLib
(1)新建项目目录myVCG,并新建子文件夹include,进入子文件夹后使用Git进行克隆,命令如下:
git clone https://github.com/cnr-isti-vclab/vcglib.git
成功后的文件夹结构如下
`-- myVCG
`-- include
`-- vcglib
|-- CMakeLists.txt
|-- LICENSE.txt
|-- README.md
|-- apps
|-- docs
|-- eigenlib
|-- img
|-- vcg
`-- wrap
(2)重命名vcglib
为vcg
2.项目创建与属性配置
(1)项目创建
使用VS2019,新建c++空项目,将位置设置为myVCG
,项目名称vcgtest
,点击创建
(2)属性配置
①在解决方案资源管理器面板,在项目名称右键,打开属性
②在打开的项目属性页,配置属性
一栏,找到VC++目录
–>包含目录
,将其设置为
path/to/your/include/vcg
③点击C/C++
一栏,找到预处理
–>预处理器定义
,输入
_CRT_SECURE_NO_WARNINGS
参数说明:
这个宏用于禁用微软C运行库(CRT)中关于安全函数的警告。
在Visual Studio中,使用不安全的函数(如strcpy、sprintf等)会触发编译器警告,建议改用更安全的替代函数(如strcpy_s、sprintf_s等)。
定义CRT_SECURE_NO_WARNINGS可以抑制这些警告,从而编译通过,但要注意,这样做可能会增加代码存在安全漏洞的风险。
至此,环境配置成功。
(3)错误解决
除上述步骤之外,在测试功能函数时,可能会出现符号无法解析的错误,如下:
严重性 代码 说明 项目 文件 行 禁止显示状态
错误 LNK2019 无法解析的外部符号 "public: unsigned __int64 __cdecl vcg::ply::PropDescriptor::memtypesize(void)const " (?memtypesize@PropDescriptor@ply@vcg@@QEBA_KXZ),函数 "public: static int __cdecl vcg::tri::io::ImporterPLY<class MyMesh>::Open(class MyMesh &,char const *,class vcg::tri::io::PlyInfo &)" (?Open@?$ImporterPLY@VMyMesh@@@io@tri@vcg@@SAHAEAVMyMesh@@PEBDAEAVPlyInfo@234@@Z) 中引用了该符号 vcgtest E:\OneDrive\Organize_myCSDN\2024年\0813_vsglib\myVCG\vcgtest\vcgtest\trimesh_smooth.obj 1
错误 LNK2019 无法解析的外部符号 "public: char const * __cdecl vcg::ply::PropDescriptor::stotypename(void)const " (?stotypename@PropDescriptor@ply@vcg@@QEBAPEBDXZ),函数 "public: static int __cdecl vcg::tri::io::ExporterPLY<class MyMesh>::Save(class MyMesh const &,char const *,bool,class vcg::tri::io::PlyInfo const &,bool (__cdecl*)(int,char const *))" (?Save@?$ExporterPLY@VMyMesh@@@io@tri@vcg@@SAHAEBVMyMesh@@PEBD_NAEBVPlyInfo@234@P6A_NH1@Z@Z) 中引用了该符号 vcgtest E:\OneDrive\Organize_myCSDN\2024年\0813_vsglib\myVCG\vcgtest\vcgtest\trimesh_smooth.obj 1
错误 LNK2019 无法解析的外部符号 "public: char const * __cdecl vcg::ply::PropDescriptor::stotype2name(void)const " (?stotype2name@PropDescriptor@ply@vcg@@QEBAPEBDXZ),函数 "public: static int __cdecl vcg::tri::io::ExporterPLY<class MyMesh>::Save(class MyMesh const &,char const *,bool,class vcg::tri::io::PlyInfo const &,bool (__cdecl*)(int,char const *))" (?Save@?$ExporterPLY@VMyMesh@@@io@tri@vcg@@SAHAEBVMyMesh@@PEBD_NAEBVPlyInfo@234@P6A_NH1@Z@Z) 中引用了该符号 vcgtest E:\OneDrive\Organize_myCSDN\2024年\0813_vsglib\myVCG\vcgtest\vcgtest\trimesh_smooth.obj 1
错误 LNK2019 无法解析的外部符号 "private: void __cdecl vcg::ply::PlyFile::compile(class vcg::ply::PlyElement *)" (?compile@PlyFile@ply@vcg@@AEAAXPEAVPlyElement@23@@Z),函数 "public: void __cdecl vcg::ply::PlyFile::SetCurElement(int)" (?SetCurElement@PlyFile@ply@vcg@@QEAAXH@Z) 中引用了该符号 vcgtest E:\OneDrive\Organize_myCSDN\2024年\0813_vsglib\myVCG\vcgtest\vcgtest\trimesh_smooth.obj 1
错误 LNK2019 无法解析的外部符号 "public: __cdecl vcg::ply::PlyFile::PlyFile(void)" (??0PlyFile@ply@vcg@@QEAA@XZ),函数 "public: static int __cdecl vcg::tri::io::ImporterPLY<class MyMesh>::Open(class MyMesh &,char const *,class vcg::tri::io::PlyInfo &)" (?Open@?$ImporterPLY@VMyMesh@@@io@tri@vcg@@SAHAEAVMyMesh@@PEBDAEAVPlyInfo@234@@Z) 中引用了该符号 vcgtest E:\OneDrive\Organize_myCSDN\2024年\0813_vsglib\myVCG\vcgtest\vcgtest\trimesh_smooth.obj 1
错误 LNK2019 无法解析的外部符号 "public: __cdecl vcg::ply::PlyFile::~PlyFile(void)" (??1PlyFile@ply@vcg@@QEAA@XZ),函数 "public: static int __cdecl vcg::tri::io::ImporterPLY<class MyMesh>::Open(class MyMesh &,char const *,class vcg::tri::io::PlyInfo &)" (?Open@?$ImporterPLY@VMyMesh@@@io@tri@vcg@@SAHAEAVMyMesh@@PEBDAEAVPlyInfo@234@@Z) 中引用了该符号 vcgtest E:\OneDrive\Organize_myCSDN\2024年\0813_vsglib\myVCG\vcgtest\vcgtest\trimesh_smooth.obj 1
错误 LNK2019 无法解析的外部符号 "public: int __cdecl vcg::ply::PlyFile::Open(char const *,int)" (?Open@PlyFile@ply@vcg@@QEAAHPEBDH@Z),函数 "public: static int __cdecl vcg::tri::io::ImporterPLY<class MyMesh>::Open(class MyMesh &,char const *,class vcg::tri::io::PlyInfo &)" (?Open@?$ImporterPLY@VMyMesh@@@io@tri@vcg@@SAHAEAVMyMesh@@PEBDAEAVPlyInfo@234@@Z) 中引用了该符号 vcgtest E:\OneDrive\Organize_myCSDN\2024年\0813_vsglib\myVCG\vcgtest\vcgtest\trimesh_smooth.obj 1
错误 LNK2019 无法解析的外部符号 "public: int __cdecl vcg::ply::PlyFile::AddToRead(char const *,char const *,int,int,unsigned __int64,int,int,int,int,unsigned __int64)" (?AddToRead@PlyFile@ply@vcg@@QEAAHPEBD0HH_KHHHH1@Z),函数 "public: int __cdecl vcg::ply::PlyFile::AddToRead(class vcg::ply::PropDescriptor const &)" (?AddToRead@PlyFile@ply@vcg@@QEAAHAEBVPropDescriptor@23@@Z) 中引用了该符号 vcgtest E:\OneDrive\Organize_myCSDN\2024年\0813_vsglib\myVCG\vcgtest\vcgtest\trimesh_smooth.obj 1
错误 LNK2019 无法解析的外部符号 "public: char const * __cdecl vcg::ply::PlyFile::ElemName(int)" (?ElemName@PlyFile@ply@vcg@@QEAAPEBDH@Z),函数 "public: static int __cdecl vcg::tri::io::ImporterPLY<class MyMesh>::Open(class MyMesh &,char const *,class vcg::tri::io::PlyInfo &)" (?Open@?$ImporterPLY@VMyMesh@@@io@tri@vcg@@SAHAEAVMyMesh@@PEBDAEAVPlyInfo@234@@Z) 中引用了该符号 vcgtest E:\OneDrive\Organize_myCSDN\2024年\0813_vsglib\myVCG\vcgtest\vcgtest\trimesh_smooth.obj 1
错误 LNK2019 无法解析的外部符号 "public: int __cdecl vcg::ply::PlyFile::ElemNumber(int)const " (?ElemNumber@PlyFile@ply@vcg@@QEBAHH@Z),函数 "public: static int __cdecl vcg::tri::io::ImporterPLY<class MyMesh>::Open(class MyMesh &,char const *,class vcg::tri::io::PlyInfo &)" (?Open@?$ImporterPLY@VMyMesh@@@io@tri@vcg@@SAHAEAVMyMesh@@PEBDAEAVPlyInfo@234@@Z) 中引用了该符号 vcgtest E:\OneDrive\Organize_myCSDN\2024年\0813_vsglib\myVCG\vcgtest\vcgtest\trimesh_smooth.obj 1
错误 LNK2019 无法解析的外部符号 "public: int __cdecl vcg::ply::PlyFile::Read(void *)" (?Read@PlyFile@ply@vcg@@QEAAHPEAX@Z),函数 "public: static int __cdecl vcg::tri::io::ImporterPLY<class MyMesh>::Open(class MyMesh &,char const *,class vcg::tri::io::PlyInfo &)" (?Open@?$ImporterPLY@VMyMesh@@@io@tri@vcg@@SAHAEAVMyMesh@@PEBDAEAVPlyInfo@234@@Z) 中引用了该符号 vcgtest E:\OneDrive\Organize_myCSDN\2024年\0813_vsglib\myVCG\vcgtest\vcgtest\trimesh_smooth.obj 1
错误 LNK2019 无法解析的外部符号 "void __cdecl vcg::ply::interpret_texture_name(char const *,char const *,char *,unsigned __int64)" (?interpret_texture_name@ply@vcg@@YAXPEBD0PEAD_K@Z),函数 "public: static int __cdecl vcg::tri::io::ImporterPLY<class MyMesh>::Open(class MyMesh &,char const *,class vcg::tri::io::PlyInfo &)" (?Open@?$ImporterPLY@VMyMesh@@@io@tri@vcg@@SAHAEAVMyMesh@@PEBDAEAVPlyInfo@234@@Z) 中引用了该符号 vcgtest E:\OneDrive\Organize_myCSDN\2024年\0813_vsglib\myVCG\vcgtest\vcgtest\trimesh_smooth.obj 1
错误 LNK1120 12 个无法解析的外部命令 vcgtest E:\OneDrive\Organize_myCSDN\2024年\0813_vsglib\myVCG\vcgtest\x64\Debug\vcgtest.exe 1
解决方案如下:
第一种:
在源文件右键,添加现有项,找到path/to/your/include/vcg/wrap/ply/plylib.cpp
,将其添加到项目中,就可避免错误。
这种方法一劳永逸,学习vcg时在不同的测试代码之间不必重复添加该文件。
第二种:
在你的代码头文件中调用wrap/ply/plylib.cpp
,具体写法为:
#include <wrap/ply/plylib.cpp>
3.样例测试
在源文件右键,添加现有项,找到path/to/your/include/vcg/apps/sample/aabb_binary_tree/aabb_binary_tree.cpp
添加文件后,直接运行,运行后输出如下:
Spatial Index Tests
---
GetClosest Test:
face : 0x0000019B2A14C298
distance : 3.603415
point : [-1.894428, 0.000000, -3.065248]
---
GetKClosest Test:
found 10 objects
---
DoRay Test:
face : 0x0000019B2A14BC18
ray t : 4.236068
---
三、文件说明
-
vcg
文件夹:-
功能: 这是VCGLib的核心库所在的文件夹,包含所有的定义和算法。这里的代码完全使用标准的C++和STL编写,并且是自包含的,即不依赖于外部文件或链接其他库,这使得该库非常灵活,可以轻松地集成到各种项目中。
-
模块:
simplex
: 定义单纯形(order 0…3),是构建复杂几何体的基础单元。complex
: 包含复形的定义、网格遍历器、局部操作(如边分裂、边折叠)和各种算法(如简化、平滑、网格生成等)。container
: 专门化的STL向量结构,用于处理单纯形的可选属性。space
: 提供基本几何实体、几何实体之间的交集操作,以及空间索引数据结构。math
: 包含一些线性代数的基本运算。
-
-
wrap
文件夹:-
功能: 这个文件夹用于封装库中的概念,提供了一些实用工具和扩展功能,帮助开发者更容易地使用VCGLib进行高级操作。
-
模块:
gl
: 使用OpenGL渲染VCG对象的工具和代码。gui
: 包含图形用户界面相关的工具和代码,帮助创建交互式应用。io_trimesh
: 用于导入和导出各种3D文件格式的模块,包括但不限于3DS、DAE、DXF、IV、OBJ、OFF、PLY、SMF、STL、VRML和RAW格式。这些模块使得VCGLib能够与多种3D格式兼容,方便数据的导入导出和处理。- 其他模块: 可能还包含其他工具和扩展,用于进一步增强VCGLib的功能。
-
-
apps
文件夹:- 功能: 这个文件夹包含使用VCGLib开发的示例应用程序或工具。这些应用展示了如何实际使用VCGLib的功能,大家可以参考这些示例来学习VCGLib的使用方法,或者直接在项目中使用这些工具。
-
docs
文件夹:- 功能: 该文件夹用于存放项目的文档,包括由Doc++生成的风格指南和手册。这些文档为用户提供了对VCGLib库的详细说明,帮助开发者更好地理解和使用该库。
至此全篇结束,欢迎大家点赞、收藏与订阅,之后将不定期更新VCGLib系列的示例操作与代码实践。
转载请标明出处
如果还有问题,欢迎在评论区留言或私信
作者:BQ
主页:bqcode.blog.csdn.net
QQ群:958124241
Learn Together!