精华内容
下载资源
问答
  • ​​​​​​1.3D模型下载地址: 网站1:... ... ...2. 以https://componentsearchengine.com/index.html为例,需要先注册,比如找方口USB3D模型GSB3211311WEU,在搜索框中...

    ​​​​​​1. 3D模型下载地址:

    2.  以https://componentsearchengine.com/index.html 为例,需要先注册,比如找方口USB3D模型GSB3211311WEU,在搜索框中搜索该器件,如下:

     3. 导入到AD中,

           1. 首先打开PCB封装库,选中要修改的封装,然后在工具栏选择Place->3D Body,鼠标变成十字架,此时按一下键盘上的TAB键,会弹出该器件的属性对话框,如下图所示:注意箭头指示的地方,最后选择右下角箭头指示的Choose...,

    然后找到刚才下载的文件夹中的一个3D文件夹,选中里面的文件,打开即可

    然后把它放到合适的位置即可

    按一下键盘数字3,即可切换到3D视图查看,

    展开全文
  • blender 3d打印 在我的Blender 3D打印入门系列的第1部分中,我介绍了基本的初步步骤,这些步骤为建立自己的3D模型并准备好进行3D打印而设置Blender环境。 在第2部分中,我将研究实际创建要打印的那些模型的过程。 在...

    blender 3d打印

    在我的Blender 3D打印入门系列的第1部分中,我介绍了基本的初步步骤,这些步骤为建立自己的3D模型并准备好进行3D打印而设置Blender环境。 在第2部分中,我将研究实际创建要打印的那些模型的过程。 在开始之前,我应该强调,Blender 不是 CAD(计算机辅助设计)工具。 相反,其主要目的是充当艺术家的工具。 Blender根本不具备CAD操作员希望看到的许多精度功能。 也就是说,许多消费者级别的3D打印机也不具有这种精度。 在3D打印和快速原型制作的情况下,Blender最适合以一种可以打印的格式快速获取您的想法,从而使您对“真实的事物”的外观和感觉有所了解。 如果此后需要更精确的工具,则至少要有一个物理对象,以便在使用CAD进行构建时可以参考。

    建模工具

    Blender在编辑模式下的标准网格建模工具本身具有强大的功能。 每天通过推顶顶点并使用简单的操作(例如拉伸E ), K )和循环剪切Ctrl + R ))创建令人难以置信的模型。 但是,一旦您破解了Blender的一些更高级的工具,一切的可能性就打开了。

    当然,对基础建模工具集感到满意仍然很有价值。 尽管有高级工具的强大功能,但仍需要一些标准建模技术来准备要打印的模型。 不过,现在让我们进入那些高级工具。

    雕刻

    在过去的10年中,3D建模的过程已经从结构化方法演变为更加直观的技术。 我们曾经不得不关心网格中每个顶点的位置以及这些顶点如何连接以形成边缘和面(也称为网格的拓扑 )。 情况不再如此,至少在创建用于3D打印的模型时不再如此。 所有这些都是由于一种称为3D雕刻的技术,Blender内置了它。

    作为一个简单的例子,以Blender的默认场景为例,该场景中有一个孤独的小立方体坐在空白处。 选中多维数据集后,使用3D视图标题中的模式选择菜单切换到雕刻模式。 您应该在鼠标光标周围看到一个红色圆圈。 这是您的雕刻笔刷。

    在Blender中切换到雕刻模式

    在3D视图的工具架T )上,“ 工具”选项卡使您能够在Blender提供的不同类型的雕刻笔刷之间进行切换,并在工作时调整每个笔刷的设置。 对于此示例,请确保使用的是SculptDraw画笔。 那应该是Blender默认为您提供的画笔。

    您现在可以尝试在多维数据集上进行雕刻(在3D视图中单击鼠标左键并将其拖动到多维数据集上),但是结果将非常乏味。 这是因为在Blender中进行雕刻的默认行为是,画笔将操纵网格中已经存在的现有顶点。 那当然有其用途,但是在基本的多维数据集上,它并不是特别有趣。 不过,我们可以解决该问题。 返回工具架 ,向下滚动到标有Dyntopo (“动态拓扑”的缩写)的面板。 展开该面板,以在顶部看到一个名为Enable Dyntopo的大按钮。 单击该按钮并启用。

    接下来,单击鼠标左键并将雕刻笔刷拖到多维数据集上。 这更有趣。 启用Dyntopo后,所有雕刻笔刷(“ Grab”和“ Rotate”笔刷除外)都将在工作时添加,删除或动态重新配置网格的拓扑。

    screenshot Dyntopo is enabled!

    Dyntopo已启用!

    雕刻是使用3D模型的一种更舒适的方法,尤其是对于任何有机的或具有复杂细节的模型。 如果您使用绘图板(如Wacom的绘图板),则更加舒适。 而本文所涵盖的一点点几乎没有刮擦表面。 我建议您先尝试一下造型笔,然后再寻求其他指导,以了解它们的工作原理。 就是说,网络上有许多很棒的参考资料和教程可以帮助您入门。

    还要记住,雕刻就像大多数艺术一样,做得越多越好。 真正提高雕刻技能水平的一种方法是应对日常挑战。 您甚至可以找到在这些日常挑战中挑战自己并在网络上分享他们的工作的人群。 在Blender社区中,“ 雕刻一月”活动非常受欢迎。 他们在一月份的每一天都在进行雕刻挑战。 同样,去年9月,我也开始了类似的日常挑战(我们称为Sculptember)。 无论您采用哪种方式,都有一个很棒的3D艺术家社区,他们可以通过Blender中的雕刻工具为您提供更好的支持,反馈和灵感。

    An example sculpt (done by me for Sculptember)

    我为Sculptember制作的一个示例雕刻

    布尔值

    雕刻本身很不错,但是如果您尝试创建本质上机械性更高的模型(有时称为硬表面模型) ,则可能会具有挑战性。 可以使用雕刻工具进行硬表面建模,但是该过程本质上不那么精确,如果没有某种帮助,很难获得漂亮,干净的边缘。 在CAD世界中,许多此类建模都是通过称为实体的参数对象完成的。 可以通过获取简单的原始对象(例如,球体,立方体,圆柱体)并将它们合并在一起,或者通过从一个对象中减去一个对象的形式来创建具有高精度的复杂对象。 这些操作称为布尔运算 ,将对象的这些组合称为逻辑AND (加), OR (减)和XOR (交集)操作的3D等效项。

    Blender不是参数建模器。 Blender主要是一个网格建模器。 但是,它仍然具有在网格之间执行布尔运算的能力。 当然,在具有不同顶点,边缘和面的网格对象上执行此类布尔运算可能具有挑战性,并且在进行3D打印模型时很容易产生令人讨厌的几何形状。 建模者在Blender中使用布尔的三种主要方法:

    1.布尔值修改器:这是在Blender中使用布尔值的最基本方法,但它也是最有可能因压力而导致脱发的方法。 该方法非常简单。 您从3D视图中的两个单独的对象开始。 选择这些对象之一(我们将其称为主要对象)后,进入“ 属性编辑器”的“ 修改器”部分,并通过左键单击“ 添加修改器”下拉按钮并从第二列中选择“布尔”来添加一个布尔修改器。

    Adding a Boolean modifier

    添加一个布尔值修饰符

    在对象新添加的布尔值修饰符中,您应该注意到有一个标为Object的空字段。 您需要该字段中另一个对象的名称。 您可以通过键入,从可用对象列表中选择,或使用吸管并在3D视图中单击该其他对象的方式将其放在此处。 默认情况下,布尔值修改器设置为执行“相交”操作,但是如果需要,您可以轻松地将其更改为“加”或“减”。

    将布尔修改器添加到网格后,似乎没有任何改变,尤其是在使用减法运算的情况下。 这是因为修饰符不会影响其他对象。 它仅使用该对象的几何来添加或删除主要对象中的几何。 另外,修饰符是非破坏性的 如果删除修改器,则返回到原始网格。 不幸的是,修饰符不是3D打印机可以理解的任何文件格式的公认部分。 因此,最终,您必须应用布尔运算符并将对网格的更改永久化。 然后,在应用后,您可以删除(或隐藏)非主要对象。

    还有另一个警告。 几乎所有3D打印机仅支持三角数据。 也就是说,所有顶点都必须连接以形成三角形。 除非采取一些预防措施,否则布尔运算符几乎总是会创建面多于三个面(通常是更多面)的面。 将由此产生的几何形状细分为三角形通常会给您带来难看的结果,例如长而细的三角形,这对于3D打印机可能是有问题的。 您可以通过细分起始网格或使用“重新网格”修改器在某种程度上解决此问题,但这可以是手动的。 实际上,使用布尔值修饰符通常是一件很手工的事情。 对于除了最简单的情况以外的所有情况,最好使用其他两个选项之一在Blender中使用布尔值。

    2. BoolTool Blender的BoolTool附加组件确实在优化对网格物体使用布尔值的工作流程方面做了很多工作。 在后台,它仍然使用Blender的Boolean修饰符,但是该插件在与Boolean交互的方式方面已对界面进行了全面改进。 BoolTool不会直接处理布尔值修改器,而是使用应用于主网格对象的几何“画笔”概念。

    The Tool Shelf with the BoolTool add-on enabled

    启用了BoolTool加载项的工具架

    此外,BoolTool的所有控件都方便地嵌套在工具架中,因此您可以使用最大化的3D视图,而不必转到属性编辑器。 仅使用Blender的布尔修改器,BoolTool还具有许多难以(或至少耗时)设置的附加功能。 其中一些功能包括更复杂的布尔运算,直接(破坏性)布尔运算,便捷的热键以及使用Blender的油脂铅笔功能绘制自定义布尔多边形的功能。 尽管BoolTool的开发版本的夜间版本中提供了BoolTool,但默认情况下它不随发行版一起提供。 您需要下载并自行安装,这是一个非常轻松的过程。

    3. HardOps HardOps是Blender的商业附加产品,但它不仅能处理布尔值。 HardOps是一整套建模工具,可帮助您在Blender中完成硬体模型。 像大多数附加组件一样,HardOps在后台使用Blender的基本功能和操作,但是您的交互针对此特定类型的建模进行了优化。 插件的功能远远超出了本文中我可以详细介绍的范围,但是我强烈建议您仔细阅读发行说明,并了解它带来的好处。 HardOps确实是一套令人印象深刻的工具。

    下周在第3部分中,我将介绍一些高级技巧,包括元球对象,使用流体模拟器连接对象,准备打印以及3D打印工具箱附加组件。

    翻译自: https://opensource.com/life/16/7/making-and-preparing-3d-models-printing-blender

    blender 3d打印

    展开全文
  • 使用Altium Designer软件如何导入3D模型 方法二 —— 网上下载已有的3D模型,然后导入封装库 上一篇博客讲述了使用Altium Designer软件导入3D模型的第一种方法,现在讲述一下第二种方法。在讲述之前,我先再重复一下...

    使用Altium Designer软件如何导入3D模型 方法二 —— 网上下载已有的3D模型,然后导入封装库

    上一篇博客讲述了使用Altium Designer软件导入3D模型的第一种方法,现在讲述一下第二种方法。在讲述之前,我先再重复一下这三种方法
    1、 请求结构工程师进行3D模型建模,然后保存STEP格式,我们导入封装库中;
    2、 网上下载已有的3D模型,然后导入封装库;
    (注:推荐一个网站https://www.3dcontentcentral.cn/
    3、 自己用Altium Designer软件建立简单的模型。

    一、从网上下载已有的3D模型

    这里还要再重复一下,一个神奇的网站,可以得到大部分的3D封装,网址如下
    链接: https://www.3dcontentcentral.cn/.
    下面讲述一下如何从这个网站下载封装,比如我们需要QFN-20封装
    1.1、 打开网址链接,搜索QFN,特殊的我只输入关键部分,因为这样可以找到更合适的,我们找到QFN-20封装,左击;在这里插入图片描述
    1.2、 根据如下图进行选项,一定要选择STEP格式的文件,点击下载在这里插入图片描述
    1.3、 点击蓝色部分的QFN-20在这里插入图片描述
    1.4、出现一个对话框,选好保存的位置之后,点击下载即可;在这里插入图片描述
    1.5、 打开文件保存的位置,解压后就能看到我们下载的文件;在这里插入图片描述

    二、将下载好的3D模型导入封装库

    3D封装已经下载完成,现将下载好的3D模型导入到封装库中,这个操作在方法一中已经讲过,但是我还是在讲一遍,加深一下我的印象,也免得来回切换我上一个博客。
    2.1、 打开PCB封装库文件,选中需要加载3D封装的元器件,点击 Place 》3D Body ( 快捷键 P-B ) ,进入3D Body [mm] 对话框在这里插入图片描述
    2.2、 按如图先选择 Generic 3D Model ,然后点击Load from file ,进入Choose Model对话框在这里插入图片描述
    2.3、 选择我们需要的STEP格式文件,点击打开,返回3D Body [mm] 对话框;在这里插入图片描述
    2.4、 点击OK,初步确定XYZ的位置与方向,随后调整XYZ方向的角度,直到确定3D的位置和方向合适;在这里插入图片描述
    2.5、 3D封装加入完成,如图所示,保存即可。在这里插入图片描述

    三、将更新的3D模型封装更新到PCB文件中

    3.1、 选中已更新好的封装,右击选中Update PCB With QFN-20 3*3MM,进入Component(s)Update Options对话框在这里插入图片描述
    3.2、 点击OK在这里插入图片描述
    3.3、 PCB文件中的3D封装已经更新完成,如图所示。在这里插入图片描述

    展开全文
  • 现代opengl 设计 3D模型文件导入显示

    千次阅读 2019-04-02 01:27:31
    利用3D模型导入库assimp, 可以读取很多种格式的3D模型文件,现在我们就用opengl 显示出来。而这需要一个桥,就是数据和opengl 显示,前文我们介绍了网格Mesh类,现在介绍model 类。有了这2个类,我们就可以完成了3D...

    利用3D模型导入库assimp, 可以读取很多种格式的3D模型文件,现在我们就用opengl 显示出来。而这需要一个桥,就是数据和opengl 显示,前文我们介绍了网格Mesh类,现在介绍model 类。有了这2个类,我们就可以完成了3D模型的显示。

    本文内容主要参照 https://learnopengl.com/  和 https://learnopengl-cn.github.io/ 学习而来。

    整个系列的代码可以在 https://github.com/JoeyDeVries/LearnOpenGL 下载。

    我自己整改为mfc 的一个例子在 http://liwensoft.com/en/view3d-2/  可以免费使用,不包含源代码,基础就是assimp。

    其功能就是可以打开各种3D 模型文件, 显示,缩放,选择,平移。然后可以转存很多种格式的3d文件。

     

    本程序在visual studio 2017 下调式通过。先看看运行效果:

    之所以只在visual studio 2017 下通过的主要原因是, 我的assimp 编译只在visual studio 2017 下通过。

    在看本文前,你需要准备好assimp 库,现代opengl 设计 assimp 3D 模型加载库 介绍了怎么编译assimp 库。

    本文也用到了Mesh类,如要细看请看  现代opengl 设计,模型导入网格类, 这个文章是为本文做准备的一个类。

    Model类

    介绍之前先把Model类的结构给你:

    class Model 
    {
        public:
            /*  函数   */
            Model(char *path)
            {
                loadModel(path);
            }
            void Draw(Shader shader);   
        private:
            /*  模型数据  */
            vector<Mesh> meshes;
            string directory;
            /*  函数   */
            void loadModel(string path);
            void processNode(aiNode *node, const aiScene *scene);
            Mesh processMesh(aiMesh *mesh, const aiScene *scene);
            vector<Texture> loadMaterialTextures(aiMaterial *mat, aiTextureType type, 
                                                 string typeName);
    };
    

    Model类包含了一个Mesh对象的vector,构造器需要我们给它一个文件路径。在构造器中,它会直接通过loadModel来加载文件。处理函数将会处理Assimp导入过程中的一部分,我们很快就会介绍它们。我们需要储存文件路径的目录,在之后加载纹理的时候还会用到它。

    Draw函数没有什么特别之处,基本上就是遍历了所有网格,并调用它们各自的Draw函数。

    void Draw(Shader shader)
    {
        for(unsigned int i = 0; i < meshes.size(); i++)
            meshes[i].Draw(shader);
    }
    

    导入3D模型到OpenGL

    要想导入一个模型,并将它转换到我们自己的数据结构中的话,首先我们需要包含Assimp对应的头文件。

    #include <assimp/Importer.hpp>
    #include <assimp/scene.h>
    #include <assimp/postprocess.h>
    

    模型导入由loadModel完成,这个代码从构造器中直接调用。在loadModel中,我们使用Assimp来加载模型至Assimp的一个叫做scene的数据结构中。你可能还记得在现代opengl 设计 assimp 3D 模型加载库中,这是Assimp数据接口的根对象。一旦我们有了这个场景对象,我们就能访问到加载后的模型中所有需要的数据。

    Assimp很棒的一点在于,它抽象掉了加载不同文件格式的所有技术细节,只需要一行代码就能完成所有的工作:

    Assimp::Importer importer;
    const aiScene *scene = importer.ReadFile(path, aiProcess_Triangulate | aiProcess_FlipUVs);
    

    我们首先声明了Assimp命名空间内的一个Importer,之后调用了它的ReadFile函数。这个函数需要一个文件路径,它的第二个参数是一些后期处理(Post-processing)的选项。除了加载文件之外,Assimp允许我们设定一些选项来强制它对导入的数据做一些额外的计算或操作。通过设定aiProcess_Triangulate,我们告诉Assimp,如果模型不是(全部)由三角形组成,它需要将模型所有的图元形状变换为三角形。aiProcess_FlipUVs将在处理的时候翻转y轴的纹理坐标(你可能还记得我们在纹理教程中说过,在OpenGL中大部分的图像的y轴都是反的,所以这个后期处理选项将会修复这个)。其它一些比较有用的选项有:

    • aiProcess_GenNormals:如果模型不包含法向量的话,就为每个顶点创建法线。
    • aiProcess_SplitLargeMeshes:将比较大的网格分割成更小的子网格,如果你的渲染有最大顶点数限制,只能渲染较小的网格,那么它会非常有用。
    • aiProcess_OptimizeMeshes:和上个选项相反,它会将多个小网格拼接为一个大的网格,减少绘制调用从而进行优化。

    Assimp提供了很多有用的后期处理指令,你可以在这里找到全部的指令。实际上使用Assimp加载模型是非常容易的(你也可以看到)。困难的是之后使用返回的场景对象将加载的数据转换到一个Mesh对象的数组。

    完整的loadModel函数将是这样的:

    void loadModel(string path)
    {
        Assimp::Importer import;
        const aiScene *scene = import.ReadFile(path, aiProcess_Triangulate | aiProcess_FlipUVs);    
    
        if(!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode) 
        {
            cout << "ERROR::ASSIMP::" << import.GetErrorString() << endl;
            return;
        }
        directory = path.substr(0, path.find_last_of('/'));
    
        processNode(scene->mRootNode, scene);
    }
    

    在我们加载了模型之后,我们会检查场景和其根节点不为null,并且检查了它的一个标记(Flag),来查看返回的数据是不是不完整的。如果遇到了任何错误,我们都会通过导入器的GetErrorString函数来报告错误并返回。我们也获取了文件路径的目录路径。

    如果什么错误都没有发生,我们希望处理场景中的所有节点,所以我们将第一个节点(根节点)传入了递归的processNode函数。因为每个节点(可能)包含有多个子节点,我们希望首先处理参数中的节点,再继续处理该节点所有的子节点,以此类推。这正符合一个递归结构,所以我们将定义一个递归函数。递归函数在做一些处理之后,使用不同的参数递归调用这个函数自身,直到某个条件被满足停止递归。在我们的例子中退出条件(Exit Condition)是所有的节点都被处理完毕。

    你可能还记得Assimp的结构中,每个节点包含了一系列的网格索引,每个索引指向场景对象中的那个特定网格。我们接下来就想去获取这些网格索引,获取每个网格,处理每个网格,接着对每个节点的子节点重复这一过程。processNode函数的内容如下:

    void processNode(aiNode *node, const aiScene *scene)
    {
        // 处理节点所有的网格(如果有的话)
        for(unsigned int i = 0; i < node->mNumMeshes; i++)
        {
            aiMesh *mesh = scene->mMeshes[node->mMeshes[i]]; 
            meshes.push_back(processMesh(mesh, scene));         
        }
        // 接下来对它的子节点重复这一过程
        for(unsigned int i = 0; i < node->mNumChildren; i++)
        {
            processNode(node->mChildren[i], scene);
        }
    }
    

    首先检查每个节点的网格索引(循环),获取对应的网格。返回的网格mesh传送到processMesh函数中,它会返回一个Mesh对象,将这个Mesh存储(push_back)在meshes (一个vector)中。

    所有网格都被处理之后,再遍历节点的所有子节点,并对它们调用相同的processMesh函数。当一个节点不再有任何子节点之后,这个函数执行完毕。

    认真的读者可能会发现,我们可以基本上忘掉处理任何的节点,只需要遍历场景对象的所有网格,就不需要为了索引做这一堆复杂的东西了。我们仍这么做的原因是,使用节点的最初想法是将网格之间定义一个父子关系。通过这样递归地遍历这层关系,我们就能将某个网格定义为另一个网格的父网格了。
    这个系统的一个使用案例是,当你想位移一个汽车的网格时,你可以保证它的所有子网格(比如引擎网格、方向盘网格、轮胎网格)都会随着一起位移。这样的系统能够用父子关系很容易地创建出来。

    然而,现在我们并没有使用这样一种系统,但如果你想对你的网格数据有更多的控制,通常都是建议使用这一种方法的。这种类节点的关系毕竟是由创建了这个模型的艺术家所定义。

    下一步就是将Assimp的数据解析到现代opengl 设计,模型导入网格类中创建的Mesh类中。

    在这个函数调用完毕,import 的作用域结束,其占用的资源也自动释放。因为我们需要的数据已经到mesh 类中了。

    从Assimp到网格

    将一个aiMesh对象转化为我们自己的网格对象不是那么困难。我们要做的只是访问网格的相关属性并将它们储存到我们自己的对象中。processMesh函数的大体结构如下:

    Mesh processMesh(aiMesh *mesh, const aiScene *scene)
    {
        vector<Vertex> vertices;
        vector<unsigned int> indices;
        vector<Texture> textures;
    
        for(unsigned int i = 0; i < mesh->mNumVertices; i++)
        {
            Vertex vertex;
            // 处理顶点位置、法线和纹理坐标
            ...
            vertices.push_back(vertex);
        }
        // 处理索引
        ...
        // 处理材质
        if(mesh->mMaterialIndex >= 0)
        {
            ...
        }
    
        return Mesh(vertices, indices, textures);
    }
    

    处理网格的过程主要有三部分:获取所有的顶点数据,获取它们的网格索引,并获取相关的材质数据。处理后的数据将会储存在三个vector当中,我们会利用它们构建一个Mesh对象,并返回它到函数的调用者那里。

    获取顶点数据非常简单,我们定义了一个Vertex结构体,我们将在每个迭代之后将它加到vertices数组中。我们会遍历网格中的所有顶点(使用mesh->mNumVertices来获取)。在每个迭代中,我们希望使用所有的相关数据填充这个结构体。顶点的位置是这样处理的:

    glm::vec3 vector; 
    vector.x = mesh->mVertices[i].x;
    vector.y = mesh->mVertices[i].y;
    vector.z = mesh->mVertices[i].z; 
    vertex.Position = vector;
    

    注意我们为了传输Assimp的数据,我们定义了一个vec3的临时变量。使用这样一个临时变量的原因是Assimp对向量、矩阵、字符串等都有自己的一套数据类型,它们并不能完美地转换到GLM的数据类型中。

    Assimp将它的顶点位置数组叫做mVertices,这其实并不是那么直观。

    处理法线的步骤也是差不多的:

    vector.x = mesh->mNormals[i].x;
    vector.y = mesh->mNormals[i].y;
    vector.z = mesh->mNormals[i].z;
    vertex.Normal = vector;
    

    纹理坐标的处理也大体相似,但Assimp允许一个模型在一个顶点上有最多8个不同的纹理坐标,我们不会用到那么多,我们只关心第一组纹理坐标。我们同样也想检查网格是否真的包含了纹理坐标(可能并不会一直如此)

    if(mesh->mTextureCoords[0]) // 网格是否有纹理坐标?
    {
        glm::vec2 vec;
        vec.x = mesh->mTextureCoords[0][i].x; 
        vec.y = mesh->mTextureCoords[0][i].y;
        vertex.TexCoords = vec;
    }
    else
        vertex.TexCoords = glm::vec2(0.0f, 0.0f);
    

    vertex结构体现在已经填充好了需要的顶点属性,我们会在迭代的最后将它压入vertices这个vector的尾部。这个过程会对每个网格的顶点都重复一遍。

    索引

    Assimp的接口定义了每个网格都有一个面(Face)数组,每个面代表了一个图元,在我们的例子中(由于使用了aiProcess_Triangulate选项)它总是三角形。一个面包含了多个索引,它们定义了在每个图元中,我们应该绘制哪个顶点,并以什么顺序绘制,所以如果我们遍历了所有的面,并储存了面的索引到indices这个vector中就可以了。

    for(unsigned int i = 0; i < mesh->mNumFaces; i++)
    {
        aiFace face = mesh->mFaces[i];
        for(unsigned int j = 0; j < face.mNumIndices; j++)
            indices.push_back(face.mIndices[j]);
    }
    

    所有的外部循环都结束了,我们现在有了一系列的顶点和索引数据,它们可以用来通过glDrawElements函数来绘制网格。然而,为了结束这个话题,并且对网格提供一些细节,我们还需要处理网格的材质。

    材质

    和节点一样,一个网格只包含了一个指向材质对象的索引。如果想要获取网格真正的材质,我们还需要索引场景的mMaterials数组。网格材质索引位于它的mMaterialIndex属性中,我们同样可以用它来检测一个网格是否包含有材质:

    if(mesh->mMaterialIndex >= 0)
    {
        aiMaterial *material = scene->mMaterials[mesh->mMaterialIndex];
        vector<Texture> diffuseMaps = loadMaterialTextures(material, 
                                            aiTextureType_DIFFUSE, "texture_diffuse");
        textures.insert(textures.end(), diffuseMaps.begin(), diffuseMaps.end());
        vector<Texture> specularMaps = loadMaterialTextures(material, 
                                            aiTextureType_SPECULAR, "texture_specular");
        textures.insert(textures.end(), specularMaps.begin(), specularMaps.end());
    }
    

    我们首先从场景的mMaterials数组中获取aiMaterial对象。接下来我们希望加载网格的漫反射和/或镜面光贴图。一个材质对象的内部对每种纹理类型都存储了一个纹理位置数组。不同的纹理类型都以aiTextureType_为前缀。我们使用一个叫做loadMaterialTextures的工具函数来从材质中获取纹理。这个函数将会返回一个Texture结构体的vector,我们将在模型的textures vector的尾部之后存储它。

    loadMaterialTextures函数遍历了给定纹理类型的所有纹理位置,获取了纹理的文件位置,并加载并和生成了纹理,将信息储存在了一个Vertex结构体中。它看起来会像这样:

    vector<Texture> loadMaterialTextures(aiMaterial *mat, aiTextureType type, string typeName)
    {
        vector<Texture> textures;
        for(unsigned int i = 0; i < mat->GetTextureCount(type); i++)
        {
            aiString str;
            mat->GetTexture(type, i, &str);
            Texture texture;
            texture.id = TextureFromFile(str.C_Str(), directory);
            texture.type = typeName;
            texture.path = str;
            textures.push_back(texture);
        }
        return textures;
    }
    

    我们首先通过GetTextureCount函数检查储存在材质中纹理的数量,这个函数需要一个纹理类型。我们会使用GetTexture获取每个纹理的文件位置,它会将结果储存在一个aiString中。我们接下来使用另外一个叫做TextureFromFile的工具函数,它将会(用stb_image.h)加载一个纹理并返回该纹理的ID。如果你不确定这样的代码是如何写出来的话,可以查看最后的完整代码。

    注意,我们假设了模型文件中纹理文件的路径是相对于模型文件的本地(Local)路径,比如说与模型文件处于同一目录下。我们可以将纹理位置字符串拼接到之前(在loadModel中)获取的目录字符串上,来获取完整的纹理路径(这也是为什么GetTexture函数也需要一个目录字符串)。

    在网络上找到的某些模型会对纹理位置使用绝对(Absolute)路径,这就不能在每台机器上都工作了。在这种情况下,你可能会需要手动修改这个文件,来让它对纹理使用本地路径(如果可能的话)。

    这就是使用Assimp导入模型的全部了。

    重大优化

    这还没有完全结束,因为我们还想做出一个重大的(但不是完全必须的)优化。大多数场景都会在多个网格中重用部分纹理。还是想想一个房子,它的墙壁有着花岗岩的纹理。这个纹理也可以被应用到地板、天花板、楼梯、桌子,甚至是附近的一口井上。加载纹理并不是一个开销不大的操作,在我们当前的实现中,即便同样的纹理已经被加载过很多遍了,对每个网格仍会加载并生成一个新的纹理。这很快就会变成模型加载实现的性能瓶颈。

    所以我们会对模型的代码进行调整,将所有加载过的纹理全局储存,每当我们想加载一个纹理的时候,首先去检查它有没有被加载过。如果有的话,我们会直接使用那个纹理,并跳过整个加载流程,来为我们省下很多处理能力。为了能够比较纹理,我们还需要储存它们的路径:

    struct Texture {
        unsigned int id;
        string type;
        aiString path;  // 我们储存纹理的路径用于与其它纹理进行比较
    };
    

    接下来我们将所有加载过的纹理储存在另一个vector中,在模型类的顶部声明为一个私有变量:

    vector<Texture> textures_loaded;
    

    之后,在loadMaterialTextures函数中,我们希望将纹理的路径与储存在textures_loaded这个vector中的所有纹理进行比较,看看当前纹理的路径是否与其中的一个相同。如果是的话,则跳过纹理加载/生成的部分,直接使用定位到的纹理结构体为网格的纹理。更新后的函数如下:

    vector<Texture> loadMaterialTextures(aiMaterial *mat, aiTextureType type, string typeName)
    {
        vector<Texture> textures;
        for(unsigned int i = 0; i < mat->GetTextureCount(type); i++)
        {
            aiString str;
            mat->GetTexture(type, i, &str);
            bool skip = false;
            for(unsigned int j = 0; j < textures_loaded.size(); j++)
            {
                if(std::strcmp(textures_loaded[j].path.data(), str.C_Str()) == 0)
                {
                    textures.push_back(textures_loaded[j]);
                    skip = true; 
                    break;
                }
            }
            if(!skip)
            {   // 如果纹理还没有被加载,则加载它
                Texture texture;
                texture.id = TextureFromFile(str.C_Str(), directory);
                texture.type = typeName;
                texture.path = str.C_Str();
                textures.push_back(texture);
                textures_loaded.push_back(texture); // 添加到已加载的纹理中
            }
        }
        return textures;
    }
    

    所以现在我们不仅有了个灵活的模型加载系统,我们也获得了一个加载对象很快的优化版本。

    有些版本的Assimp在使用调试版本或者使用IDE的调试模式下加载模型会非常缓慢,所以在你遇到缓慢的加载速度时,可以试试使用发布版本。

    你可以在这里找到优化后Model类的完整源代码。

    和箱子模型告别

    所以,让我们导入一个由真正的艺术家所创造的模型,替代我这个天才的作品(你要承认,这些箱子可能是你看过的最漂亮的立方体了),测试一下我们的实现吧。由于我不想让我占太多的功劳,我会偶尔让别的艺术家也加入我们,这次我们将会加载Crytek的游戏孤岛危机(Crysis)中的原版纳米装(Nanosuit)。这个模型被输出为一个.obj文件以及一个.mtl文件,.mtl文件包含了模型的漫反射、镜面光和法线贴图(这个会在后面学习到),你可以在这里下载到(稍微修改之后的)模型,注意所有的纹理和模型文件应该位于同一个目录下,以供加载纹理。

    注意

    主题内容基本引用上述网站,在调试过程中,有以下几点需要注意:

    1:在主程序中

    Model ourModel(FileSystem::getPath("resources/objects/nanosuit/nanosuit.obj")); 这行需要修改成你的实际目录,比如

    Model ourModel("D:\\study17\\nanosuit\\nanosuit.obj");  

    2: 在model.h 文件中,有个得到目录的代码行,需要修改成如下:

    directory = path.substr(0, path.find_last_of('\\'));

    最开始我程序可以运行,但是一片黑乎乎的,我debug 到这行,发现directory 没有得到其需要的值。

    3:提供的模型可以完美显示,但不是所有都能这样,主要是有些文件不完整,比如obj就需要.mtl  和其他图片纹理文件。没有纹理的文件不能显示。

    4: 利用本文的内容,也可以移植导入3D模型到MFC的界面里。

     

    展开全文
  • Altium Designer导入3D模型 进入3D图形下载网址:http://www.3dcontentcentral.cn/ 参考博客网址:https://blog.csdn.net/tq384998430/article/details/79584404(注:更详细的可以参考该地址) 选择好对应的格式...
  • Cocos2d-x 3D模型渲染

    千次阅读 2018-11-11 20:40:44
    Cocos2d-x 3D模型渲染 声明:本文使用的是cocos2d-x-3.17的代码 文章中的提到的测试代码下载地址https://gitee.com/Kyle12/Cocos2dRenderStudy 3D模型 Cocos2d支持渲染*.fbx和*.obj两种3D模型,*.obj模型可以...
  • 3D模型
  • 作为一名3D打印爱好者,您有没有想过打印一个自己大脑的3D模型呢?现在机会来了,近日在开源硬件热站Instructables上,一个昵称为3d_printed_brain的用户贴出了一个简单的教程,教您一步步地创建自己的3D打印大脑。...
  • AD20 在pcb中添加3d模型

    千次阅读 2020-08-22 08:07:17
    3D模型下载的网址: https://www.3dcontentcentral.cn 上面有很多共享的3D文件,输入型号搜索,注册后可以下载。 ...第一步:下载3D 模型 (.step文件) 第二步:打开PCB库 第三步:调整3D模型的角度和高度 ...
  • 3D模型读取库:Assimp

    万次阅读 2015-07-23 11:09:50
    Assimp(Open Asset Import Library)是一个支持读取多种模型资源的开源库,当前最新的版本是3.0版,支持读取以下类型的3D模型: Collada ( .dae )Blender 3D ( .blend )3ds Max 3DS ( .3ds )3ds Max ASE ( .ase )...
  • ANDROID应用中嵌入Unity3D视图(展示3D模型)

    万次阅读 多人点赞 2014-07-24 00:10:21
    本文通过一个在Android中展示3D模型的实例,介绍如何将Unity3d以View的形式嵌入到Android应用中。并提供Deom和代码下载
  • c#开发环境下用Directx载入3D模型

    千次阅读 2017-06-29 10:34:05
    而c#相关的资料比较少,最近做的一个项目中需要用到一个3D模型,而开发环境是visual c#,没办法,就四处搜集资料,查找相关的资料,然后找到了几篇相关的博文,不过这些博文说的都太仔细,有些内容又丢失了一些...
  • three.js加载3D模型(.glb格式和.gltf格式)

    万次阅读 多人点赞 2019-07-05 10:52:03
    要使用three.js实现在网页中加载3D模型进行实时展示的功能,首先要了解three.js 什么是three.js,Three.js是一款开源的主流3D绘图JS引擎,简单点,可以将它理解为three+js就可以了,three表示3D,js表示JavaScript...
  • 渐入渐出的效果,使用系统自带的shader似乎是无法达到这样的效果,如设置shader为Standard,Rendering Mode 设置为Transparent,将透明度调制0,最后的效果还是看得到模型。3、 Shader代码Shader "Transparent/...
  • 【微信小程序】Three.js 加载3d模型

    千次阅读 热门讨论 2020-04-11 18:26:18
    微信小程序实现从外部加载3d模型 1.3d模型的几种格式? 2.怎样加载3d模型? 1.模型的格式 小程序支持从外部加载3d模型的几种格式有: a.obj格式 b.gltf格式 c.glb格式 d.fbx格式 就列举这几种 2.加载3d模型 用 gltf ...
  • Cesium.js 加载3D模型

    万次阅读 2016-02-29 14:25:22
    一、Cesuimjs介绍Cesiunjs是一套GIS行业中进行地图渲染的js库,该库...二、加载过程因为cesium只支持GLTF格式的3D描述文件,而笔者拿到的.max文件。因此要实现从max文件转换到gltf文件过程,然后通过cesium相应的api...
  • SceneKit一个加载3D模型的神奇框架

    千次阅读 2016-12-23 10:46:36
    由于我们的项目需要使用3D模型,将3D模型展示到客户端,如果用OpenGL太麻烦,
  • 玩转iOSARkit以及3D模型

    2019-06-23 21:50:54
    文章目录前言解析下代码planeBox换个模型推荐的3D模型网站下载模型注意事项将新模型放到项目里渲染模型两个诡异错误Scene is modified in a rendering callback of another scene.模型出来模型大小调整 前言 学AR...
  • SmartSplant3D模型导入Unity

    千次阅读 2020-07-08 16:10:44
    模型文件后缀名是.vue,前端框架有个VUE框架,导致查到的资料大部分是VUE框架的。 用Navisworks导入,有插件:http://www.mrgeng.com/navisworks-loader-plugin-for-smart-3d-vue-file/ 另外有个视频是SmartPlant...
  • 提问:3D模型展示商品香吗? 香!当然香。 当3D建模成为电商网购应用的左膀右臂,大同小异的产品首图就有了焕然一新的呈现面貌!商品3D模型360°全方位展示,细节更丰富,辅以线上虚拟“看、试、穿、戴”,提供...
  • gltf是一种更适合web项目使用的3d模型格式。相比较其他模型格式他的优势十分明显:大幅减少模型容量,有效节省带宽。根据本人体验,可以至少可以节省5倍的空间。现在很多3d人间都已经支持该格式了,就连自带的3d画图...
  • 【C++】3D模型载入演示demo by浅墨

    千次下载 热门讨论 2013-02-18 03:57:12
    其中的3D模型使用的是初音,模型质量很高,可以自己用鼠标和键盘控制视角。 【Visual C++】游戏开发笔记之【浅墨DirectX提高班】系列博文 配套详细注释源码之十二 源码配套博文 《【Visual C++】游戏开发笔记四十...
  • OBJ(3D模型)文件格式

    万次阅读 2018-08-16 13:42:28
    在最近的3D编程中,想开始做一些多模型的Demo,而网上显然没有那么多直接可供DirectX使用的模型文件(.x),而3D模型文件格式中的obj文件则具有较好的通用性,不仅支持各类3D建模软件的互相导入导出,在Maya上还可以...
  • 外部3D模型格式很多,常用的有gltf、obj、glb等,但是也没有形成类似于2d图片jpg、png这样具有统一标准的规模,同时目前好像没有一个通用的加载器可以兼容所有的,所以也带来一些总觉得乱七八糟的困扰。所以我们这里...
  • unity3d模型旋转和模型导出obj

    千次阅读 2015-01-07 17:35:13
    unity3d中写脚本实现模型的颜色变化和旋转,注意如果模型设置为static是旋转了的。 功能描述:鼠标落到模型模型颜色变化,按下鼠标模型开始旋转。 脚本代码如下: using UnityEngine; using System.Collections; ...
  • opengles之3D模型加载(obj模型文件)

    千次阅读 热门讨论 2016-09-09 17:39:05
    模型加载类 package test.com.opengles9_1; import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import java.util.ArrayList; import android.content.
  • Altium制作DC002的PCB封装和3D模型

    千次阅读 2018-09-29 13:50:42
    Altium制作DC002的PCB封装和3D模型 常用的电源连接器(Dc Power Jack Connector)DC002、DC005等等型号的3D模型在网上很难找到合适的,我们可以选择CUI 公司生产的电源连接器来替代,因为CUI 公司生产的每一款电源...
  • 3d模型轻量级查看器-Autodesk FBX Review

    万次阅读 2018-10-19 10:52:31
    本人在百度查找轻量级模型查看器,如supermodel,meshview都有一定缺点,如supermodel无法在选择模型打开方式的时候进行打开,只能通过软件自带的openmodel打开,但打开之后的obj模型没有材质,所以模型的颜色很难看...
  • 【Altium Designer】AD18 导入3D模型

    千次阅读 2020-06-23 17:29:51
    AD18 导入3D模型,更新对应封装,使得在 PCB 的 3D 视图中可以展现。

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 21,587
精华内容 8,634
关键字:

下载的3d模型打不开