基于OpenCASCADE自制三维建模软件(十一)使用ASSIMP导入导出
基于OpenCASCADE自制三维建模软件(十一)使用ASSIMP导入导出
2019年08月06日 23:54:20 Jelly_Lee2 阅读数 73 文章标签: 三维建模CADOpenCASCADEOCC 更多
分类专栏: 基于OpenCASCADE自制三维建模软件
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/jelatine/article/details/98611472
文章目录
- 一、导入模型
- 二、导出模型
- 项目仓库
一、导入模型
// cmainwindow.cpp
void CMainWindow::on_actionImport_triggered()
{// 获取ASSIMP支持的导入格式Importer t_importer;std::string szOut;t_importer.GetExtensionList(szOut); // ASSIMP支持的导入格式// 筛选文件格式QString t_assimp=tr("ASSIMP (") +QString::fromStdString(szOut) +tr(")");QString all_filter;all_filter+=t_assimp;// 获取被打开的文件路径QString filename = QFileDialog::getOpenFileName(this,tr("open file"),"D:/models",all_filter);...
}
inline void GetExtensionList(std::string& szOut) const;
使用QFileDialog::getOpenFileName
函数显示导入文件框。
// cmodel.cpp
// CModel::CModel
{...//从外部文件中加载模型Importer t_importer;const aiScene *t_scene=t_importer.ReadFile(_filepath.toStdString(),aiProcess_Triangulate | aiProcess_FlipUVs | aiProcess_CalcTangentSpace);if(!t_scene || t_scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !t_scene->mRootNode) // if is Not Zero{qDebug() << "ERROR::ASSIMP:: " << t_importer.GetErrorString();return;}// 构造根节点及所有子节点m_process_nodes(t_scene->mRootNode, t_scene, true);
}
将模型的文件路径输入到Assimp::Importer
的成员函数ReadFile
中,返回场景aiScene
结构体。把结构体放入m_process_nodes
函数中处理场景的节点。
// cmodel.cpp
// CModel::m_process_nodesaiMatrix4x4 t_matrix=_node->mTransformation; // 获取转换坐标系// 获取旋转矩阵的缩放比例ai_real t_scaling_x = aiVector3D(t_matrix.a1,t_matrix.a2,t_matrix.a3).Length();ai_real t_scaling_y = aiVector3D(t_matrix.b1,t_matrix.b2,t_matrix.b3).Length();ai_real t_scaling_z = aiVector3D(t_matrix.c1,t_matrix.c2,t_matrix.c3).Length();// 从 aiMatrix4x4 转换成 gp_Trsf 形式gp_Trsf t_transfer;t_transfer.SetValues(t_matrix.a1 / t_scaling_x, t_matrix.a2 / t_scaling_x, t_matrix.a3 / t_scaling_x, t_matrix.a4,t_matrix.b1 / t_scaling_y, t_matrix.b2 / t_scaling_y, t_matrix.b3 / t_scaling_y, t_matrix.b4,t_matrix.c1 / t_scaling_z, t_matrix.c2 / t_scaling_z, t_matrix.c3 / t_scaling_z, t_matrix.c4);
// cmodel.cpp
// void CModel::m_process_nodes(const aiNode *_node, const aiScene *_scene, bool _is_root)for(unsigned int imesh = 0; imesh < _node->mNumMeshes; imesh++){aiMesh* t_mesh = _scene->mMeshes[_node->mMeshes[imesh]]; // 获取当前网格// 遍历网格的所有面for(unsigned int iface = 0; iface < t_mesh->mNumFaces; iface++){t_mesh->mMaterialIndex;aiFace t_face = t_mesh->mFaces[iface];BRepBuilderAPI_MakePolygon t_polygon;// 遍历面的所有顶点for(unsigned int ivertex = 0; ivertex < t_face.mNumIndices; ivertex++){// 转换顶点储存模式gp_Pnt t_pnt=gp_Pnt(t_mesh->mVertices[t_face.mIndices[ivertex]].x,t_mesh->mVertices[t_face.mIndices[ivertex]].y,t_mesh->mVertices[t_face.mIndices[ivertex]].z);t_polygon.Add(t_pnt); // 添加顶点}t_polygon.Close(); // 闭合顶点t_topo_face = BRepBuilderAPI_MakeFace (t_polygon); // 通过闭合的线构造面if(!t_topo_face.IsNull()){t_build_tool.Add (t_compound, t_topo_face); // 将面加入到复合体中}}//! 材质信息aiMaterial* material = _scene->mMaterials[t_mesh->mMaterialIndex]; //通过索引获取网格在环境中的材质t_occ_material = m_material_transfer(material); // 从ASSIMP格式转换到OCC材质格式}
// cmodel.cpp
// void CModel::m_process_nodes(const aiNode *_node, const aiScene *_scene, bool _is_root)for(unsigned int i = 0; i < _node->mNumChildren; i++){m_process_nodes(_node->mChildren[i], _scene , t_is_next_root); // 构造子节点}
上一节中使用了m_material_transfer
函数将ASSIMP的aiMaterial
结构体内容转换到OpenCASCADE中的Graphic3d_MaterialAspect
形式。
// cmodel.cpp
// Graphic3d_MaterialAspect CModel::m_material_transfer(aiMaterial *_material)Graphic3d_MaterialAspect t_result;t_result.SetMaterialType(Graphic3d_MATERIAL_PHYSIC);Quantity_Color t_occ_colors[Graphic3d_TypeOfReflection_NB];t_occ_colors[Graphic3d_TOR_AMBIENT] = Quantity_Color (Graphic3d_Vec3 (0.2f, 0.2f, 0.2f));t_occ_colors[Graphic3d_TOR_DIFFUSE] = Quantity_Color (Graphic3d_Vec3 (0.2f, 0.2f, 0.2f));t_occ_colors[Graphic3d_TOR_SPECULAR] = Quantity_Color (Graphic3d_Vec3 (1.0f, 1.0f, 1.0f));Standard_ShortReal t_occ_shininess = 0.039f;
// cmodel.cpp
// Graphic3d_MaterialAspect CModel::m_material_transfer(aiMaterial *_material)aiString name; // 材质名称 原始数据if (AI_SUCCESS==aiGetMaterialString(_material,AI_MATKEY_NAME,&name)){t_result.SetMaterialName(name.C_Str());}// 环境光aiColor4D ambient; // 环境光 原始数据if(AI_SUCCESS ==aiGetMaterialColor(_material, AI_MATKEY_COLOR_AMBIENT, &ambient)){t_occ_colors[Graphic3d_TOR_AMBIENT]=Quantity_Color(ambient.r,ambient.g,ambient.b,Quantity_TOC_RGB);t_result.SetAmbientColor(t_occ_colors[Graphic3d_TOR_AMBIENT]);}// 漫反射aiColor4D diffuse; // 漫反射 原始数据if(AI_SUCCESS ==aiGetMaterialColor(_material, AI_MATKEY_COLOR_DIFFUSE, &diffuse)){t_occ_colors[Graphic3d_TOR_DIFFUSE]=Quantity_Color(diffuse.r,diffuse.g,diffuse.b,Quantity_TOC_RGB);t_result.SetDiffuseColor(t_occ_colors[Graphic3d_TOR_DIFFUSE]);}// 镜面光aiColor4D specular; // 镜面光 原始数据if(AI_SUCCESS ==aiGetMaterialColor(_material, AI_MATKEY_COLOR_SPECULAR, &specular)){t_occ_colors[Graphic3d_TOR_SPECULAR]=Quantity_Color(specular.r,specular.g,specular.b,Quantity_TOC_RGB);t_result.SetSpecularColor(t_occ_colors[Graphic3d_TOR_SPECULAR]);}// 反光度float shininess; // 反光度 原始数据if(AI_SUCCESS ==aiGetMaterialFloat(_material, AI_MATKEY_SHININESS, &shininess)){t_occ_shininess=shininess/128.0; // 由OpenGL值转换成VRML97// OCC的反光度表示方式只接受0到1之间,否则报错t_occ_shininess = t_occ_shininess<1.0 ? t_occ_shininess:1.0;t_occ_shininess = t_occ_shininess<0.0 ? 0.0:t_occ_shininess;t_result.SetShininess(t_occ_shininess); // 设置反光度}
二、导出模型
// cmainwindow.cpp
// void CMainWindow::on_actionExport_triggered()if(m_3d_widget->m_get_context()->NbSelected() == 0){// 无选择则弹出提示框QMessageBox::warning(this,tr("Export Error"),tr("There is no object selected!"));return; // 不执行操作}
// cmainwindow.cpp
// void CMainWindow::on_actionExport_triggered()QString t_all_filter; // 所有文件过滤器QHash<QString,const char *> t_hash_format; // 格式过滤器与文档描述哈希表Exporter t_export; // 导出器for(int i=0; i<t_export.GetExportFormatCount(); i++) // 遍历ASSIMP允许导出的格式{const aiExportFormatDesc *t_format_desc = t_export.GetExportFormatDescription(i); // 获取每个文档描述// 文档过滤器QString t_single_format = QString(t_format_desc->description)+QString("(*.%1)").arg(t_format_desc->fileExtension);t_hash_format.insert(t_single_format,t_format_desc->id); // 插入格式过滤器与文档描述哈希表t_all_filter += t_single_format; // 添加单个文档过滤到整体过滤器if(i != t_export.GetExportFormatCount()-1) // 最后一个不添加分行{t_all_filter+=";;"; // 分行}}
打开保存文件对话框,通过返回值filename
获得保存的文件名,并通过t_selected_filter
获取用户选择的过滤器
// cmainwindow.cpp
// void CMainWindow::on_actionExport_triggered()QString t_selected_filter; // 被选择的过滤器// 打开文件保存提示框QString filename = QFileDialog::getSaveFileName(this,tr("Save"),".",t_all_filter,&t_selected_filter);if(filename.isEmpty()) // 若文件名为空,则不执行操作{return; // 不执行操作}
// cmainwindow.cpp
// void CMainWindow::on_actionExport_triggered() // 导出模型文件CModel::m_export_model(filename,t_hash_format.value(t_selected_filter),m_3d_widget->m_get_context());
// cmodel.cpp
// static bool m_export_model(QString _filename , const char *_format_id,Handle(AIS_InteractiveContext) _context);Exporter exporter;// 定义场景aiScene *t_scene = new aiScene();// 单一材质// 创建根节点t_scene->mRootNode=new aiNode();// 创建子节点int t_NumChildrenNode = _context->NbSelected();aiNode **t_node_list=new aiNode*[t_NumChildrenNode];t_scene->mNumMaterials=t_NumChildrenNode;t_scene->mMaterials = new aiMaterial*[t_NumChildrenNode];// 定义场景所有网格t_scene->mNumMeshes = t_NumChildrenNode;t_scene->mMeshes = new aiMesh*[t_NumChildrenNode];int t_index = 0;
// cmodel.cpp
// static bool m_export_model(QString _filename , const char *_format_id,Handle(AIS_InteractiveContext) _context);for ( _context->InitSelected(); _context->MoreSelected(); _context->NextSelected() ){aiNode *t_node = t_node_list[t_index] = new aiNode();t_node->mNumMeshes=1; // 一个网格t_node->mNumChildren=0; // 无子节点t_node->mMeshes = new uint[1]; //一个网格地址t_node->mMeshes[0] = t_index; // 网格地址索引aiMesh* pMesh = t_scene->mMeshes[t_index] = new aiMesh(); // 创建地址0的网格pMesh->mMaterialIndex = t_index; // 网格材质Standard_Integer aNbNodes = 0;Standard_Integer aNbTriangles = 0;Handle(AIS_InteractiveObject) obj = _context->SelectedInteractive();......}
// cmodel.cpp
// static bool m_export_model(QString _filename , const char *_format_id,Handle(AIS_InteractiveContext) _context);
// for ( _context->InitSelected(); _context->MoreSelected(); _context->NextSelected() )Handle(AIS_Shape) ais_shape = Handle(AIS_Shape)::DownCast(obj);Graphic3d_MaterialAspect shpae_material(ais_shape->Material());aiMaterial* pMaterial = t_scene->mMaterials[t_index] = new aiMaterial();Quantity_Color amb=shpae_material.AmbientColor();aiColor4D ambient(amb.Red(),amb.Green(),amb.Blue(),1.0);pMaterial->AddProperty(&ambient,1,AI_MATKEY_COLOR_AMBIENT);Quantity_Color diff=shpae_material.DiffuseColor();aiColor4D diffuse(diff.Red(),diff.Green(),diff.Blue(),1.0);pMaterial->AddProperty(&diffuse,1,AI_MATKEY_COLOR_DIFFUSE);Quantity_Color spec=shpae_material.SpecularColor();aiColor4D specular(spec.Red(),spec.Green(),spec.Blue(),1.0);pMaterial->AddProperty(&specular,1,AI_MATKEY_COLOR_SPECULAR);Standard_ShortReal shin=shpae_material.Shininess();pMaterial->AddProperty(&shin,1,AI_MATKEY_SHININESS);
// cmodel.cpp
// static bool m_export_model(QString _filename , const char *_format_id,Handle(AIS_InteractiveContext) _context);
// for ( _context->InitSelected(); _context->MoreSelected(); _context->NextSelected() )TopoDS_Shape theShape = ais_shape->Shape();// calculate total number of the nodes and trianglesfor (TopExp_Explorer anExpSF (theShape, TopAbs_FACE); anExpSF.More(); anExpSF.Next()){TopLoc_Location aLoc;Handle(Poly_Triangulation) aTriangulation = BRep_Tool::Triangulation (TopoDS::Face (anExpSF.Current()), aLoc);if (! aTriangulation.IsNull()){aNbNodes += aTriangulation->NbNodes ();aNbTriangles += aTriangulation->NbTriangles ();}}pMesh->mNumVertices = aNbNodes;pMesh->mNumFaces = aNbTriangles;
// cmodel.cpp
// static bool m_export_model(QString _filename , const char *_format_id,Handle(AIS_InteractiveContext) _context);
// for ( _context->InitSelected(); _context->MoreSelected(); _context->NextSelected() )int index=0;int face_index=0;// fill temporary triangulationStandard_Integer aNodeOffset = 0;for (TopExp_Explorer anExpSF (theShape, TopAbs_FACE); anExpSF.More(); anExpSF.Next()){TopLoc_Location aLoc;Handle(Poly_Triangulation) aTriangulation = BRep_Tool::Triangulation (TopoDS::Face (anExpSF.Current()), aLoc);const TColgp_Array1OfPnt& aNodes = aTriangulation->Nodes();const Poly_Array1OfTriangle& aTriangles = aTriangulation->Triangles();// copy nodesgp_Trsf aTrsf = aLoc.Transformation();for (Standard_Integer aNodeIter = aNodes.Lower(); aNodeIter <= aNodes.Upper(); ++aNodeIter){gp_Pnt aPnt = aNodes (aNodeIter);aPnt.Transform (aTrsf);qDebug()<<"nodes "<<aPnt.X()<<aPnt.Y()<<aPnt.Z();vp[index].Set(aPnt.X(),aPnt.Y(),aPnt.Z());vn[index].Set(0.0,0.0,1.0);index++;}// copy trianglesconst TopAbs_Orientation anOrientation = anExpSF.Current().Orientation();for (Standard_Integer aTriIter = aTriangles.Lower(); aTriIter <= aTriangles.Upper(); ++aTriIter){Poly_Triangle aTri = aTriangles (aTriIter);Standard_Integer anId[3];aTri.Get (anId[0], anId[1], anId[2]);if (anOrientation == TopAbs_REVERSED){// Swap 1, 2.Standard_Integer aTmpIdx = anId[1];anId[1] = anId[2];anId[2] = aTmpIdx;}// Update nodes according to the offset.anId[0] += aNodeOffset;anId[1] += aNodeOffset;anId[2] += aNodeOffset;aiFace& face = pMesh->mFaces[face_index++];face.mIndices = new unsigned int[face.mNumIndices = 3];face.mIndices[0]=anId[0]-1;face.mIndices[1]=anId[1]-1;face.mIndices[2]=anId[2]-1;}aNodeOffset += aNodes.Size();}t_index++;
完善aiScene
结构体的内容,使用Assimp::Exporter
的Export
方法将t_scene
对象的内容保存到文件中,文件格式以_format_id
参数决定
// cmodel.cpp
// static bool m_export_model(QString _filename , const char *_format_id,Handle(AIS_InteractiveContext) _context);// 根节点加入子节点t_scene->mRootNode->addChildren(t_NumChildrenNode,t_node_list);exporter.Export(t_scene , _format_id , _filename.toStdString());
项目仓库
https://github.com/Jelatine/JellyCAD
基于OpenCASCADE自制三维建模软件(十一)使用ASSIMP导入导出相关推荐
- 基于OpenCASCADE自制三维建模软件(六)瓶子模型例程
文章目录 概述 预备知识 模型 规格 一.构建轮廓 定义支持点 定义几何图形 定义拓扑结构 完成轮廓 二.构建瓶身 拉伸轮廓 倒角 添加瓶颈 创造中空的实体 三.构建螺纹 创建表面 定义二维曲线 创建 ...
- 基于OpenCASCADE自制三维建模软件(三)搭建开发环境
文章目录 一.参考环境 二.安装Qt与VS2015 三.OCC第三方库介绍 1. Tcl 2. FreeType 2 3. FreeImage 4. FFmpeg 5. TBB 6. VTK 四.安装 ...
- 基于OpenCASCADE自制三维建模软件(五)鼠标模式
文章目录 一.选择导航模式 二.平移 三.缩放 四.旋转 五.实际效果 项目仓库 鼠标控制模式用于三维空间可视化导航,通过鼠标的按键及少数键盘按键的组合,可以实现对三维视图的平移.缩放.选择等操作. ...
- 基于OpenCASCADE自制三维建模软件(四)实现三维显示界面
文章目录 一.配置系统变量及QMake文件 二.创建界面 三.编译并运行项目 四.问题处理 项目仓库 一.配置系统变量及QMake文件 在系统环境变量中添加CASROOT变量,将OpenCASCADE ...
- 基于OpenCASCADE自制三维建模软件(七)立方体、圆柱、球、圆锥、圆环
文章目录 一.立方体 1.构造 2.实例 二.圆柱 1.构造 2.实例 三.球 1.构造 2.实例 四.圆锥 1.构造 2.实例 五.圆环 1.构造 2.实例 项目仓库 Open CASCADE有现成 ...
- 轻便易用的三维建模软件
用python写了个简易的三维建模软件Draft,抛砖引玉一下,小伙伴们可以在此基础上完善功能.采用wxPython库和OpenGL,由于OpenGL只支持Linux,所以软件的编写调试运行都是在Li ...
- Rhinoceros mac版(犀牛三维建模软件)中文版
犀牛Rhinoceros mac版是非常受欢迎的一款三维建模软件,rhinoceros mac 中文版可应用于三维动画制作.机械设计.建筑设计.工业制造等,具备全面的NURBS.网格.分析.制图等工具 ...
- 【第三课】UAV倾斜摄影测量三维建模软件
前言 各大厂商的UAV管家软件可以直接将航拍影像下载到电脑,当我们获得航片之后,检查像片质量和数量是否和之前规划的一致,像片质量如何?是否存在质量较差的影像.如果存在大面积的航片质量不佳,那么需要补飞 ...
- 三维建模软件的插件安装教程——3D Max
大家在使用三维建模软件3D Max的时候一定遇到过插件不知道如何安装的情况,今天我将把常用插件的类型和扩展名罗列如下方便大家安装收集也算抛砖引玉望各位高手查漏补缺不吝赐教. 3DSMAX的插件名后缀主 ...
最新文章
- Mysql4种方式避免重复插入数据!
- category使用 objc_setAssociatedObject/objc_getAssociatedObject 实现添加属性
- node内存配置(--max-old-space-size)
- 用NPOI从DataBase到Excel '2
- 全球44家机构,55位大佬,历时两年,打造最强NLG评测基准!
- android 开发 佳博打印模板_电商在打印快递电子面单时的常见问题及解决方法
- CCS6的graph变灰解决办法
- 迈高图手机版_迈高图最新版
- 教你ogg怎么转mp3格式
- Firefox浏览器修改背景颜色为豆沙绿
- 计算机的认识文档,对计算机专业的认识.pdf
- Java验证图片格式
- Ubuntu14.04/16.0 安装N卡驱动
- 错误代码warning C4013: ‘sqrt‘ undefined; assuming extern returning int怎么解决?
- 解决方案的四种落地形态
- 关于在node项目使用ioredis遇到的几个坑
- “碳中和”研究为什么需要气象数据
- 力扣解题思路:488. 祖玛游戏
- OpenLayers 6.13 新特性
- mysql一列数除以一列数和_MySQL查询将列除以100?