推荐:将 NSDT场景编辑器 加入你的3D开发工具链

介绍

网格对象是由三角形和顶点组成的形状

  在 CHAI3D 中,多边形网格是定义多面体对象形状的顶点和三角形的集合。

  顶点是一个位置以及其他信息,例如颜色、法线矢量和纹理坐标。由直线连接的两个顶点成为一条边。三个顶点通过三条边相互连接,定义一个三角形,这是欧几里得空间中最简单的多边形。

  网格对象可以平移、旋转或调整大小,并具有分配给它们的材质和纹理属性。 以下代码演示如何创建由 4 个顶点和 2 个三角形组成的带纹理的正方形。

using namespace chai3d;
// create a mesh
object = new cMesh();
// create a texture map
object->m_texture = cTexture2d::create();
// load a texture file
object->m_texture->loadFromFile("myTexture.jpg");
// enable texture mapping
object1->setUseTexture(true);
// set material to white
object1->m_material->setWhite();
// create vertices
int vertex0 = object0->newVertex();
int vertex1 = object0->newVertex();
int vertex2 = object0->newVertex();
int vertex3 = object0->newVertex();
// set position, surface normal, and texture coordinate for vertex 0
object0->m_vertices->setLocalPos(vertex0,-0.1,-0.1, 0.0);
object0->m_vertices->setNormal(vertex0, 0.0, 0.0, 1.0);
object0->m_vertices->setTexCoord(vertex0, 0.0, 0.0);
// set position, surface normal, and texture coordinate for vertex 1
object0->m_vertices->setLocalPos(vertex1, 0.1,-0.1, 0.0);
object0->m_vertices->setNormal(vertex1, 0.0, 0.0, 1.0);
object0->m_vertices->setTexCoord(vertex1, 1.0, 0.0);
// set position, surface normal, and texture coordinate for vertex 2
object0->m_vertices->setLocalPos(vertex2, 0.1, 0.1, 0.0);
object0->m_vertices->setNormal(vertex2, 0.0, 0.0, 1.0);
object0->m_vertices->setTexCoord(vertex2, 1.0, 1.0);
// set position, surface normal, and texture coordinate for vertex 3
object0->m_vertices->setLocalPos(vertex3,-0.1, 0.1, 0.0);
object0->m_vertices->setNormal(vertex3, 0.0, 0.0, 1.0);
object0->m_vertices->setTexCoord(vertex3, 0.0, 1.0);
// create two triangles by assigning their vertex IDs
object0->m_triangles->newTriangle(vertex0, vertex1, vertex2);
object0->m_triangles->newTriangle(vertex0, vertex2, vertex3);

渲染选项

材质

  材料属性定义表面如何反射光线。他们通过定义颜色值来实现这一点,其方式与灯光大致相同。材质具有漫射(直射)光、环境(散射)光和镜面反射(反射)光的颜色值,但这些值定义了光的分量如何从材质表面反射。更多信息可以在有关材料的部分找到。

  材质属性可以启用或禁用,并且需要在世界中至少使用一个光源才能使对象可见。

using namespace chai3d;
// create a mesh
cMesh* mesh = new cMesh();
// add mesh to world
world->addChild(mesh);
// build mesh using a cylinder primitive
cCreatePipe(mesh,
0.15,
0.05,
0.06,
32,
1,
cVector3d(-0.05,-0.20, 0.0),
cMatrix3d(cDegToRad(0), cDegToRad(0), cDegToRad(170), C_EULER_ORDER_XYZ)
);
// enable material property
cylinder->setUseMaterial(true);
// (1) set material by simply assigning a color name
mesh->m_material->setBlueCornflower();
// (2) or set material by assigning a color values for each component
mesh->m_material->m_ambient.set(0.2, 0.1, 0.1);
mesh->m_material->m_diffuse.set(0.6, 0.3, 0.3);
mesh->m_material->m_specular.set(1.0, 1.0, 1.0);
mesh->m_material->setShininess(10);

顶点颜色

  可以为网格的每个顶点指定不同的颜色值。如果三角形的三个顶点共享不同的颜色,则三角形上任何点的颜色都是通过三种顶点颜色的插值来计算的。

三角形和顶点颜色

  如果启用了材料属性,顶点颜色将与材料颜色组合在一起。通常将材质设置为白色并为不同的顶点分配颜色以产生所需的光晕。如果禁用材质属性,则忽略所有光源,并使用纯顶点颜色来渲染对象。

using namespace chai3d;
// create a mesh
cMesh* mesh = new cMesh();
// add mesh to world
world->addChild(mesh);
// create three new vertices
int vertex0 = mesh->newVertex();
int vertex1 = mesh->newVertex();
int vertex2 = mesh->newVertex();
// set position of each vertex
mesh->m_vertices->setLocalPos(vertex0, 0.0, 0.0, 0.0);
mesh->m_vertices->setLocalPos(vertex1, 0.0, 1.0, 0.0);
mesh->m_vertices->setLocalPos(vertex2, 1.0, 1.0, 0.0);
// assign color value to each vertex
cColorf color(1.0, 0.2, 0.2);
mesh->m_vertices->setColor(vertex0, color);
mesh->m_vertices->setColor(vertex1, color);
mesh->m_vertices->setColor(vertex2, color);
// create new triangle from vertices
mesh->newTriangle(vertex0, vertex1, vertex2);
// enable vertex colors
mesh->setUseVertexColors(true);
// compute surface normals
mesh->computeAllNormals();

纹理映射

纹理映射

  纹理贴图将应用(映射)到形状或多边形的表面。此过程类似于将图案纸应用于纯白框。多边形中的每个顶点都通过显式分配或过程定义分配一个纹理坐标(在 2d 情况下也称为 UV 坐标)。然后,在多边形的表面插值图像采样位置,以生成视觉结果,该结果似乎比使用有限数量的多边形可以实现的更丰富。

  要了解如何在 CHAI3D 中创建纹理,请参阅本页顶部的第一个示例。

线框图

  三角形可以在实心或线模式下渲染。

(左)固体模式。(右)线框模式。

using namespace chai3d;
// enable wireframe rendering mode
mesh->setWireMode(true);
// enable solid rendering mode
mesh->setWireMode(false);

边缘

  要同时渲染边和三角形,CHAI3D 提供了显示三角形的选项,并覆盖根据相邻三角形之间所需的最小角度选择的边子集。

(左)实心和边缘。(右)仅边缘。

using namespace chai3d;
// compute all edges for which adjacent triangles have more than 40 degrees angle
mesh->computeAllEdges(40);
// set line width of edges and color
cColorf color;
color.setBlack();
mesh->setEdgeProperties(1, color);
// (1) enable surfaces and edges
mesh->setShowTriangles(true);
mesh->setShowEdges(true);
// (2) enable edges only
mesh->setShowTriangles(false);
mesh->setShowEdges(true);

面部剔除

  背面剔除确定网格对象的三角形是否可见。这是图形管道中的一个步骤,用于测试三角形中的顶点在投影到屏幕上时是否按顺时针顺序显示。

using namespace chai3d;

// enable culling
object->setUseCulling(true);

  如果启用了面部剔除,但投影在屏幕上的多边形具有逆时针缠绕,则它已旋转为背离相机,不会被绘制。

  该过程通过减少程序绘制的多边形数量,使渲染对象更快、更高效。例如,在城市街道场景中,通常不需要在建筑物背对摄影机的侧面绘制多边形;它们被面向相机的侧面完全遮挡。

  通常,如果背面剔除仅包含封闭和不透明的几何体,则可以假定在渲染场景中不会产生可见的伪影。在包含透明多边形的场景中,通过 Alpha 合成过程,后向多边形可能会变得可见。

透明度、半透明性和混合

渲染相机的半透明镜头

  透明的物理材质显示其后面的对象未被遮挡,并且不会从其表面反射光线。透明玻璃是一种近乎透明的材料。虽然玻璃允许大多数光线不受遮挡地通过,但实际上它也反射了一些光。完全透明的材料是完全看不见的。

  半透明物理材质显示其后面的对象,但这些对象被半透明材质遮挡。此外,半透明材质会反射照射到它的一些光线,使材料可见。半透明材料的物理示例包括透明布料、薄塑料和烟熏玻璃。

  透明和半透明通常是同义词。既不透明也不半透明的材料是不透明的。

  混合是OpenGL的机制,用于将帧缓冲中已有的颜色与传入基元的颜色组合在一起。然后,这种组合的结果将存储回帧缓冲器中。混合经常用于模拟半透明的物理材质。一个例子是渲染汽车的烟熏玻璃挡风玻璃。驾驶员和内饰仍然可见,但它们被烟熏玻璃的深色所掩盖。

表面法线

渲染网格的顶点法线

  在 CHAI3D 中启用照明时,法线矢量用于确定在指定顶点或表面上接收的光量。如果尚未定义曲面法线,则可以通过取该三角形两条边的向量叉积来计算每个三角形的法线。 出于调试目的,可以使用以下调用显示曲面法线:

using namespace chai3d;
// compute all surface normals
mesh->computeAllNormals();
// set normal properties for display
cColorf color;
color.setOrangeTomato();
mesh->setNormalsProperties(0.01, color);
// display surface normals
mesh->setShowNormals(true);

多网格对象

介绍

  由于网格对象每个对象仅包含一个材质和纹理属性,因此创建使用材质和纹理集合的网格需要使用称为 cMultiMesh 的不同类,该类将网格列表连接在一起。通过在单独的网格对象中根据三角形的材质和纹理属性来组织三角形,可以有效地构建和渲染具有丰富属性集的复杂对象。

using namespace chai3d;
// create a multi mesh object
cMultiMesh* multiMesh = new cMultiMesh();
// add multi mesh object to world
world->addChild(multiMesh);
// create a first mesh
cMesh* mesh1 = multiMesh->newMesh();
// create a second mesh
cMesh* mesh2 = multiMesh->newMesh();

文件支持

  CHAI3D 支持 3DS、OBJ 和 SLT 文件格式来导入或导出模型。如果您希望导入不同格式的文件,可以使用Blender或Visual Enterprise Author(以前称为Deep Exploration)等应用程序来编辑文件并将其转换为所需的格式。

using namespace chai3d;

// load 3DS model file
multiMesh->loadFromFile("myModel.3ds");
// load OBJ model file
multiMesh->loadFromFile("myModel.obj");
// load STL model file
multiMesh->loadFromFile("myModel.stl");

// save model to 3DS file
multiMesh->saveToFile("myModel.3ds");
// save model to OBJ file
multiMesh->saveToFile("myModel.obj");
// save model to STL file
multiMesh->saveToFile("myModel.stl");

碰撞检测

  碰撞检测器用于计算射线与组成网格(或多网格)的任何三角形之间的交点。为了使此操作快速进行,CHAI3D 使用边界体积层次结构或 BVH。BVH 是一组几何对象上的树结构。所有几何对象都包裹在构成树的叶节点的边界体积中。然后将这些节点分组为小集合,并包含在较大的边界体积中。反过来,这些也以递归方式分组并封闭在其他较大的边界体积中,最终导致树结构在树的顶部具有单个边界体积。边界体积层次结构用于有效地支持对几何对象集的多项操作,例如在触觉交互计算、光线追踪或鼠标选择的碰撞检测中。

轴对齐边界体积层次结构

  在 CHAI3D 中,必须在定义三角形后生成边界体积层次结构。如果修改了三角形或移动了顶点,则必须再次计算层次结构。更新碰撞树时,正确包含世界上使用的最大触觉点的半径非常重要。此信息用于创建足够大的包络,以检测与半径小于或等于定义阈值的接触点的任何交互。

using namespace chai3d;
// create axis aligned bounding volume hierarchy
multiMesh->createAABBCollisionDetector(toolRadius);

触觉效果

网格对象的触觉渲染

  为了触觉渲染网格对象,CHAI3D使用由Ruspini和Khatib开发的虚拟“手指代理”算法,类似于Zilles和Salisbury提出的“上帝对象”。虚拟代理是替代虚拟环境中物理手指或探测器的代表性对象。

Ruspini和Khatib的手指代理算法

  上图说明了虚拟代理的运动,因为触觉设备的位置发生了变化。代理的运动试图始终朝着目标移动。当畅通无阻时,代理直接向目标移动。当代理遇到障碍物时,无法直接移动,但代理仍可以通过沿一个或多个约束曲面移动来缩短到目标的距离。选择运动以局部最小化到目标的距离。当代理无法减少其与目标的距离时,它将停止在本地最小配置处。力是通过对触觉设备和代理位置之间的虚拟弹簧进行建模来计算的。弹簧的刚度在材料属性中定义。

using namespace chai3d;
// create collision detector
mesh->createAABBCollisionDetector(toolRadius);
// set haptic properties
mesh->m_material->setStiffness(1000);
mesh->m_material->setStaticFriction(0.3);
mesh->m_material->setDynamicFriction(0.4);

  还可以通过材料属性等级激活和调整其他触觉效果。触觉效果使用势场算法,任何通用形状对象也支持这些算法。请注意,网格对象目前不支持磁性效果。

using namespace chai3d;
// create a haptic stick-slip effect
mesh->createEffectStickSlip();
// set haptic properties
mesh->m_material->setStickSlipForceMax(5.0);
mesh->m_material->setStickSlipStiffness(1000);

3D建模学习工作室翻译整理,转载请标明出处!

chai 3D 之网格对象的更多相关文章

  1. three.js的raycaster射线无法获取visible为false的网格对象

    在做网格对象拖放时,需要创建一个不可见的参考平面,如果将平面对象设置为visible,则射线对象无法获取该平面,就无法进行位置计算. onDocumentMouseMove: function (e) ...

  2. pcl曲面网格模型的三种显示方式

    pcl网格模型有三种可选的显示模式,分别是面片模式(surface)显示,线框图模式(wireframe)显示,点模式(point)显示.默认为面片模式进行显示.设置函数分别为: void pcl:: ...

  3. WebGL 入门-WebGL简介与3D图形学

    什么是WebGL? WebGL是一项使用JavaScript实现3D绘图的技术,浏览器无需插件支持,Web开发者就能借助系统显卡(GPU)进行编写代码从而呈现3D场景和对象. WebGL基于OpenG ...

  4. 第1部分: 游戏引擎介绍, 渲染和构造3D世界

    原文作者:Jake Simpson译者: 向海Email:GameWorldChina@myway.com ---------------------------------------------- ...

  5. Three.js开发指南---创建,加载高级网格和几何体(第八章)

    本章的主要内容: 一, 通过Three.js自带的功能来组合和合并已有的几何体,创建出新的几何体 二, 从外部资源中加载网格和几何体 1 前面的章节中,我们学习到,一个几何体创建的网格,想使用多个材质 ...

  6. Cocos2d-x学习笔记(十二)3D特效

    特效类即是GridAction类,其实就是基于网格的3D动作类.需开启OpenGL的深度缓冲,否则容易3D失真. 下边是一个snippet,创建网格对象,并将其添加到当前layer:同时,将进行3D特 ...

  7. 用编程方式编写Babylon格式的宇宙飞船3D模型

    使用上一篇文章(https://www.cnblogs.com/ljzc002/p/9353101.html)中提出的方法,编写一个简单的宇宙飞船3D模型,在这篇文章中对模型制作流程和数学计算步骤进行 ...

  8. 使用Chrome控制台进行3D模型编辑的尝试

    前言:3D模型编辑的核心是对顶点位置和纹理颜色的编辑,这个研究的目的在于寻找一种通过编程方式直接对模型进行编辑的方法,这种编辑方法和时下流行的通过鼠标点选.拖拽进行编辑的方法之间的关系,和前端编程中“ ...

  9. ogre3D学习基础1 -- 核心对象与脚本技术

    一.核心对象介绍1.命名空间 Ogre3d使用了C++的特性--命名空间,可以防止命名混淆.使用方法也简单,using namespace Ogre;或者直接在使用时加上“Ogre::”的前缀,如Og ...

  10. Unity3D研究院之游戏对象的访问绘制线与绘制面详解(十七)

    一眨眼学习Unity3D 也有一段时间了,基本已经拿下了这套游戏引擎,回过头来想想以前写的RPG 游戏引擎,越来越发现以前写的就是垃圾.人果然是要不断学习与不断进步,好好学习,天天向上.哇咔咔- 加油 ...

随机推荐

  1. 《HTTP权威指南》– 4.HTTP连接管理

    浏览器解析URL流程: 浏览器解析出域名: 浏览器查询这个主机名的IP地址: 浏览器获得端口号: 浏览器发起到主机名IP地址端口的80连接: 浏览器向服务器发送一条HTTP–GET报文: 浏览器从服务 ...

  2. JavaScript:七大基础数据类型:大整数bigint

    因为数值number有表示范围,所以当我们需要精确表示更大的数字时,我们需要用到大整数bigint: 事实上,大整数可以精确表示任意长度的整数: 我们可以通过在整数的末尾添加字母n,来声明它是一个大整 ...

  3. Flutter异常监控 - 壹 | 从Zone说起

    开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第3天,点击查看活动详情 如果你正需要处理Flutter异常捕获,那么恭喜你,找对地了,这里从根源上给你准备了Flutter异常捕获 ...

  4. [python] NetworkX实例

    文章目录 NetworkX实例 1. 基础Basic 2. 绘图Drawing 3. 图标Graph NetworkX实例 代码下载地址 NetworkX 2.4版本的通用示例性示例.本教程介绍了约定 ...

  5. C++初探索

    C++初探索 前言 C++ 和 C 的区别主要在8个方面: 输入和输出 引用 inline函数 函数默认值 函数重载 模板函数 new 和 delete namespace 我仅对印象不深的地方做了总 ...

  6. C#调用js库的方法

    前言 用.net6开发一个Winform程序,处理Excel文件,并把结果导出Excel文件. 要用到两个算法,一是turf.js库的booleanPointInPolygon方法,判断经纬度坐标是否 ...

  7. OSI七层协议补充与socket套节字

    OSI七层协议补充与socket套节字 一.传输层之TCP与UDP协议 TCP与UDP协议都是用来规定通信方式的,数据传输过程中能够遵循的协议有很多其中TCP协议和UDP协议是较为常见的两个. 1.T ...

  8. 行为型模式 - 解释器模式Interpreter

    学习而来,代码是自己敲的.也有些自己的理解在里边,有问题希望大家指出. 模式的定义与特点 解释器模式(Interperter Pattern),给定一个语言,定义它的文法表示,并定义一个解释器,这个解 ...

  9. python开发云主机类型管理脚本

    python开发云主机类型管理脚本 开发flavor_manager.py程序,来完成云主机类型管理的相关操作. 该文件拥有以下功能: 根据命令行参数,创建一个云主机类型,返回response. 查询 ...

  10. elasticsearch中使用bucket script进行聚合

    目录 1.背景 2.需求 3.准备数据 3.1 mapping 3.2 插入数据 4.bucket_script聚合的语法 5.聚合 5.1 根据月份分组排序 5.2 统计每个月卖了多少辆车 5.3 ...